Logging Refactor

This replaces the current epee logging system with our oxen::log
library. It replaces the easylogging library with spdlog, removes the
macros and replaces with functions and standardises how we call the
logs.
This commit is contained in:
Sean Darcy 2022-09-13 16:57:56 +10:00 committed by Jason Rhinelander
parent 0f85299e1f
commit d7992b5940
No known key found for this signature in database
GPG Key ID: C4992CE7A88D4262
249 changed files with 25249 additions and 34357 deletions

12
.gitmodules vendored
View File

@ -7,9 +7,6 @@
[submodule "external/randomx"]
path = external/randomx
url = https://github.com/oxen-io/loki-randomXL
[submodule "external/loki-mq"]
path = external/oxen-mq
url = https://github.com/oxen-io/loki-mq.git
[submodule "external/googletest"]
path = external/googletest
url = https://github.com/google/googletest.git
@ -25,9 +22,6 @@
[submodule "external/ghc-filesystem"]
path = external/ghc-filesystem
url = https://github.com/gulrak/filesystem.git
[submodule "external/fmt"]
path = external/fmt
url = https://github.com/fmtlib/fmt.git
[submodule "external/Catch2"]
path = external/Catch2
url = https://github.com/catchorg/Catch2
@ -43,3 +37,9 @@
[submodule "external/oxen-encoding"]
path = external/oxen-encoding
url = https://github.com/oxen-io/oxen-encoding.git
[submodule "external/oxen-logging"]
path = external/oxen-logging
url = https://github.com/oxen-io/oxen-logging
[submodule "external/oxen-mq"]
path = external/oxen-mq
url = https://github.com/oxen-io/oxen-mq.git

View File

@ -299,7 +299,6 @@ if(NOT MANUAL_SUBMODULES)
endif()
check_submodule(external/uWebSockets uSockets)
check_submodule(external/ghc-filesystem)
check_submodule(external/SQLiteCpp)
endif()
endif()
@ -491,7 +490,6 @@ if(NOT BUILD_STATIC_DEPS)
endif()
add_subdirectory(external)
target_compile_definitions(easylogging PRIVATE AUTO_INITIALIZE_EASYLOGGINGPP)
if(USE_DEVICE_TREZOR)
include(CheckTrezor)

View File

@ -338,11 +338,9 @@ eof:
color_prompt += "\001\033[0m\002";
m_stdin_reader.get_readline_buffer().set_prompt(color_prompt);
#else
epee::set_console_color(epee::console_color_yellow, true);
std::cout << prompt;
if (' ' != prompt.back())
std::cout << ' ';
epee::reset_console_color();
std::cout.flush();
#endif
}
@ -370,26 +368,22 @@ eof:
break;
if (m_stdin_reader.eos())
{
MGINFO("EOF on stdin, exiting");
std::cout << std::endl;
break;
}
if (m_cancel)
{
MDEBUG("Input cancelled");
cmd_handler(std::nullopt);
m_cancel = false;
continue;
}
if (!get_line_ret)
{
MERROR("Failed to read line.");
}
string_tools::trim(command);
LOG_PRINT_L2("Read command: " << command);
if (command.empty())
{
continue;
@ -405,7 +399,6 @@ eof:
}
catch (const std::exception &ex)
{
LOG_ERROR("Exception at [console_handler], what=" << ex.what());
}
}
if (exit_handler)

View File

@ -31,84 +31,12 @@
#ifdef __cplusplus
#include <string>
#include "easylogging++.h"
#include <sstream>
#include <iostream>
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "default"
#define MAX_LOG_FILE_SIZE 104850000 // 100 MB - 7600 bytes
#define MAX_LOG_FILES 50
#define CLOG_ENABLED(level, cat) ELPP->vRegistry()->allowed(el::Level::level, cat)
#define LOG_ENABLED(level) CLOG_ENABLED(level, OXEN_DEFAULT_LOG_CATEGORY)
#define MCLOG_TYPE(level, cat, type, x) do { \
if (ELPP->vRegistry()->allowed(level, cat)) { \
el::base::Writer(level, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \
} \
} while (0)
#define MCLOG(level, cat, x) MCLOG_TYPE(level, cat, el::base::DispatchAction::NormalLog, x)
#define MCLOG_FILE(level, cat, x) MCLOG_TYPE(level, cat, el::base::DispatchAction::FileOnlyLog, x)
#define MCFATAL(cat,x) MCLOG(el::Level::Fatal,cat, x)
#define MCERROR(cat,x) MCLOG(el::Level::Error,cat, x)
#define MCWARNING(cat,x) MCLOG(el::Level::Warning,cat, x)
#define MCINFO(cat,x) MCLOG(el::Level::Info,cat, x)
#define MCDEBUG(cat,x) MCLOG(el::Level::Debug,cat, x)
#define MCTRACE(cat,x) MCLOG(el::Level::Trace,cat, x)
#define MCLOG_COLOR(level,cat,color,x) MCLOG(level,cat,"\033[1;" color "m" << x << "\033[0m")
#define MCLOG_RED(level,cat,x) MCLOG_COLOR(level,cat,"31",x)
#define MCLOG_GREEN(level,cat,x) MCLOG_COLOR(level,cat,"32",x)
#define MCLOG_YELLOW(level,cat,x) MCLOG_COLOR(level,cat,"33",x)
#define MCLOG_BLUE(level,cat,x) MCLOG_COLOR(level,cat,"34",x)
#define MCLOG_MAGENTA(level,cat,x) MCLOG_COLOR(level,cat,"35",x)
#define MCLOG_CYAN(level,cat,x) MCLOG_COLOR(level,cat,"36",x)
#define MLOG_RED(level,x) MCLOG_RED(level,OXEN_DEFAULT_LOG_CATEGORY,x)
#define MLOG_GREEN(level,x) MCLOG_GREEN(level,OXEN_DEFAULT_LOG_CATEGORY,x)
#define MLOG_YELLOW(level,x) MCLOG_YELLOW(level,OXEN_DEFAULT_LOG_CATEGORY,x)
#define MLOG_BLUE(level,x) MCLOG_BLUE(level,OXEN_DEFAULT_LOG_CATEGORY,x)
#define MLOG_MAGENTA(level,x) MCLOG_MAGENTA(level,OXEN_DEFAULT_LOG_CATEGORY,x)
#define MLOG_CYAN(level,x) MCLOG_CYAN(level,OXEN_DEFAULT_LOG_CATEGORY,x)
#define MFATAL(x) MCFATAL(OXEN_DEFAULT_LOG_CATEGORY,x)
#define MERROR(x) MCERROR(OXEN_DEFAULT_LOG_CATEGORY,x)
#define MWARNING(x) MCWARNING(OXEN_DEFAULT_LOG_CATEGORY,x)
#define MINFO(x) MCINFO(OXEN_DEFAULT_LOG_CATEGORY,x)
#define MDEBUG(x) MCDEBUG(OXEN_DEFAULT_LOG_CATEGORY,x)
#define MTRACE(x) MCTRACE(OXEN_DEFAULT_LOG_CATEGORY,x)
#define MLOG(level,x) MCLOG(level,OXEN_DEFAULT_LOG_CATEGORY,x)
#define MGINFO(x) MCINFO("global",x)
#define MGINFO_RED(x) MCLOG_RED(el::Level::Info, "global",x)
#define MGINFO_GREEN(x) MCLOG_GREEN(el::Level::Info, "global",x)
#define MGINFO_YELLOW(x) MCLOG_YELLOW(el::Level::Info, "global",x)
#define MGINFO_BLUE(x) MCLOG_BLUE(el::Level::Info, "global",x)
#define MGINFO_MAGENTA(x) MCLOG_MAGENTA(el::Level::Info, "global",x)
#define MGINFO_CYAN(x) MCLOG_CYAN(el::Level::Info, "global",x)
#define IFLOG(level, cat, type, init, x) \
do { \
if (ELPP->vRegistry()->allowed(level, cat)) { \
init; \
el::base::Writer(level, __FILE__, __LINE__, ELPP_FUNC, type).construct(cat) << x; \
} \
} while(0)
#define MIDEBUG(init, x) IFLOG(el::Level::Debug, OXEN_DEFAULT_LOG_CATEGORY, el::base::DispatchAction::NormalLog, init, x)
#define LOG_ERROR(x) MERROR(x)
#define LOG_PRINT_L0(x) MWARNING(x)
#define LOG_PRINT_L1(x) MINFO(x)
#define LOG_PRINT_L2(x) MDEBUG(x)
#define LOG_PRINT_L3(x) MTRACE(x)
#define LOG_PRINT_L4(x) MTRACE(x)
#define MLOG_SET_THREAD_NAME(x) el::Helpers::setThreadName(x)
#ifndef LOCAL_ASSERT
#include <assert.h>
#if (defined _MSC_VER)
@ -119,13 +47,6 @@
#endif
std::string mlog_get_default_log_path(const char *default_filename);
void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size = MAX_LOG_FILE_SIZE, const std::size_t max_log_files = MAX_LOG_FILES);
void mlog_set_categories(const char *categories);
std::string mlog_get_categories();
void mlog_set_log_level(int level);
void mlog_set_log(const char *log);
namespace epee
{
namespace debug
@ -146,12 +67,10 @@ namespace debug
catch(const std::exception& ex) \
{ \
(void)(ex); \
LOG_ERROR("Exception at [" << location << "], what=" << ex.what()); \
return return_val; \
}\
catch(...)\
{\
LOG_ERROR("Exception at [" << location << "], generic exception \"...\"");\
return return_val; \
}
@ -161,39 +80,15 @@ namespace debug
#define CATCH_ENTRY_L3(lacation, return_val) CATCH_ENTRY(lacation, return_val)
#define CATCH_ENTRY_L4(lacation, return_val) CATCH_ENTRY(lacation, return_val)
#define ASSERT_MES_AND_THROW(message) {LOG_ERROR(message); std::stringstream ss; ss << message; throw std::runtime_error(ss.str());}
#define ASSERT_MES_AND_THROW(message) {std::stringstream ss; ss << message; throw std::runtime_error(ss.str());}
#define CHECK_AND_ASSERT_THROW_MES(expr, message) do {if(!(expr)) ASSERT_MES_AND_THROW(message);} while(0)
#ifndef CHECK_AND_ASSERT
#define CHECK_AND_ASSERT(expr, fail_ret_val) do{if(!(expr)){LOCAL_ASSERT(expr); return fail_ret_val;};}while(0)
#endif
#ifndef CHECK_AND_ASSERT_MES
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message) do{if(!(expr)) {LOG_ERROR(message); return fail_ret_val;};}while(0)
#endif
#ifndef CHECK_AND_NO_ASSERT_MES_L
#define CHECK_AND_NO_ASSERT_MES_L(expr, fail_ret_val, l, message) do{if(!(expr)) {LOG_PRINT_L##l(message); /*LOCAL_ASSERT(expr);*/ return fail_ret_val;};}while(0)
#endif
#ifndef CHECK_AND_NO_ASSERT_MES
#define CHECK_AND_NO_ASSERT_MES(expr, fail_ret_val, message) CHECK_AND_NO_ASSERT_MES_L(expr, fail_ret_val, 0, message)
#endif
#ifndef CHECK_AND_NO_ASSERT_MES_L1
#define CHECK_AND_NO_ASSERT_MES_L1(expr, fail_ret_val, message) CHECK_AND_NO_ASSERT_MES_L(expr, fail_ret_val, 1, message)
#endif
#ifndef CHECK_AND_ASSERT_MES_NO_RET
#define CHECK_AND_ASSERT_MES_NO_RET(expr, message) do{if(!(expr)) {LOG_ERROR(message); return;};}while(0)
#endif
#ifndef CHECK_AND_ASSERT_MES2
#define CHECK_AND_ASSERT_MES2(expr, message) do{if(!(expr)) {LOG_ERROR(message); };}while(0)
#define CHECK_AND_ASSERT_MES(expr, fail_ret_val, message) do{if(!(expr)) {return fail_ret_val;};}while(0)
#endif
enum console_colors
@ -209,9 +104,6 @@ enum console_colors
};
bool is_stdout_a_tty();
void set_console_color(int color, bool bright);
void reset_console_color();
}
extern "C"
@ -225,12 +117,6 @@ extern "C"
#define ATTRIBUTE_PRINTF
#endif
bool merror(const char *category, const char *format, ...) ATTRIBUTE_PRINTF;
bool mwarning(const char *category, const char *format, ...) ATTRIBUTE_PRINTF;
bool minfo(const char *category, const char *format, ...) ATTRIBUTE_PRINTF;
bool mdebug(const char *category, const char *format, ...) ATTRIBUTE_PRINTF;
bool mtrace(const char *category, const char *format, ...) ATTRIBUTE_PRINTF;
#ifdef __cplusplus
}

View File

@ -51,9 +51,6 @@
#include <functional>
#include <random>
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "net"
#define AGGRESSIVE_TIMEOUT_THRESHOLD 120 // sockets
#define NEW_CONNECTION_TIMEOUT_LOCAL 1200000 // 2 minutes
#define NEW_CONNECTION_TIMEOUT_REMOTE 10000 // 10 seconds
@ -103,7 +100,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
m_local(false),
m_ready_to_close(false)
{
MDEBUG("test, connection constructor set m_connection_type="<<m_connection_type);
}
PRAGMA_WARNING_DISABLE_VS(4355)
@ -113,11 +109,9 @@ PRAGMA_WARNING_DISABLE_VS(4355)
{
if(!m_was_shutdown)
{
MTRACE("[sock " << socket().native_handle() << "] Socket destroyed without shutdown.");
shutdown();
}
MTRACE("[sock " << socket().native_handle() << "] Socket destroyed");
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
@ -141,9 +135,10 @@ PRAGMA_WARNING_DISABLE_VS(4355)
boost::system::error_code ec;
auto remote_ep = socket().remote_endpoint(ec);
CHECK_AND_NO_ASSERT_MES(!ec, false, "Failed to get remote endpoint: " << ec.message() << ':' << ec.value());
CHECK_AND_NO_ASSERT_MES(remote_ep.address().is_v4() || remote_ep.address().is_v6(), false, "only IPv4 and IPv6 supported here");
if (ec)
throw std::runtime_error(std::string("Failed to get remote endpoint: ") + ec.message() + ":" + std::to_string(ec.value()));
if (!remote_ep.address().is_v4() && !remote_ep.address().is_v6())
throw std::runtime_error("Only IPv4 and IPv6 are supported here");
if (remote_ep.address().is_v4())
{
const unsigned long ip_ = boost::asio::detail::socket_ops::host_to_network_long(remote_ep.address().to_v4().to_ulong());
@ -176,17 +171,8 @@ PRAGMA_WARNING_DISABLE_VS(4355)
context = t_connection_context{};
context.set_details(random_uuid, std::move(real_remote), is_income);
boost::system::error_code ec;
auto local_ep = socket().local_endpoint(ec);
CHECK_AND_NO_ASSERT_MES(!ec, false, "Failed to get local endpoint: " << ec.message() << ':' << ec.value());
MTRACE("[sock " << socket_.native_handle() << "] new connection from " << print_connection_context_short(context) <<
" to " << local_ep.address().to_string() << ':' << local_ep.port() <<
", total sockets objects " << get_state().sock_count);
if(static_cast<shared_state&>(get_state()).pfilter && !static_cast<shared_state&>(get_state()).pfilter->is_remote_host_allowed(context.m_remote_address))
{
MDEBUG("[sock " << socket().native_handle() << "] host denied " << context.m_remote_address.host_str() << ", shutdowning connection");
close();
return false;
}
@ -211,7 +197,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
boost::asio::detail::socket_option::integer< IPPROTO_IP, IP_TOS >
optionTos( tos );
socket().set_option( optionTos );
//MDEBUG("Set ToS flag to " << tos);
#endif
boost::asio::ip::tcp::no_delay noDelayOption(false);
@ -226,7 +211,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
bool connection<t_protocol_handler>::request_callback()
{
TRY_ENTRY();
MDEBUG("[" << print_connection_context_short(context) << "] request_callback");
// Use safe_shared_from_this, because of this is public method and it can be called on the object being deleted
auto self = safe_shared_from_this();
if(!self)
@ -252,9 +236,7 @@ PRAGMA_WARNING_DISABLE_VS(4355)
auto self = safe_shared_from_this();
if(!self)
return false;
//MTRACE("[sock " << socket().native_handle() << "] add_ref, m_peer_number=" << mI->m_peer_number);
std::lock_guard lock{self->m_self_refs_lock};
//MTRACE("[sock " << socket().native_handle() << "] add_ref 2, m_peer_number=" << mI->m_peer_number);
if(m_was_shutdown)
return false;
++m_reference_count;
@ -268,7 +250,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
{
TRY_ENTRY();
std::shared_ptr<connection<t_protocol_handler> > back_connection_copy;
LOG_TRACE_CC(context, "[sock " << socket().native_handle() << "] release");
std::lock_guard lock{m_self_refs_lock};
CHECK_AND_ASSERT_MES(m_reference_count, false, "[sock " << socket().native_handle() << "] m_reference_count already at 0 at connection<t_protocol_handler>::release() call");
// is this the last reference?
@ -284,7 +265,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
void connection<t_protocol_handler>::call_back_starter()
{
TRY_ENTRY();
MDEBUG("[" << print_connection_context_short(context) << "] fired_callback");
m_protocol_handler.handle_qued_callback();
CATCH_ENTRY_L0("connection<t_protocol_handler>::call_back_starter()", void());
}
@ -306,9 +286,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
address = endpoint.address().to_string();
port = boost::lexical_cast<std::string>(endpoint.port());
}
MDEBUG(" connection type " << to_string( m_connection_type ) << " "
<< socket().local_endpoint().address().to_string() << ":" << socket().local_endpoint().port()
<< " <--> " << context.m_remote_address.str() << " (via " << address << ":" << port << ")");
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
@ -316,7 +293,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
std::size_t bytes_transferred)
{
TRY_ENTRY();
//MINFO("[sock " << socket().native_handle() << "] Async read calledback.");
if (!e)
{
@ -354,7 +330,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
} while(delay > 0);
} // any form of sleeping
//MINFO("[sock " << socket().native_handle() << "] RECV " << bytes_transferred);
logger_handle_net_read(bytes_transferred);
context.m_last_recv = std::chrono::steady_clock::now();
context.m_recv_cnt += bytes_transferred;
@ -362,7 +337,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
bool recv_res = m_protocol_handler.handle_recv(buffer_.data(), bytes_transferred);
if(!recv_res)
{
//MINFO("[sock " << socket().native_handle() << "] protocol_want_close");
//some error in protocol, protocol handler ask to close connection
m_want_close_connection = true;
bool do_shutdown = false;
@ -381,19 +355,15 @@ PRAGMA_WARNING_DISABLE_VS(4355)
boost::bind(&connection<t_protocol_handler>::handle_read, connection<t_protocol_handler>::shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)));
//MINFO("[sock " << socket().native_handle() << "]Async read requested.");
}
}else
{
MTRACE("[sock " << socket().native_handle() << "] Some not success at read: " << e.message() << ':' << e.value());
if(e.value() != 2)
{
MTRACE("[sock " << socket().native_handle() << "] Some problems at read: " << e.message() << ':' << e.value());
shutdown();
}
else
{
MTRACE("[sock " << socket().native_handle() << "] peer closed connection");
bool do_shutdown = false;
{
std::lock_guard lock{m_send_que_lock};
@ -461,21 +431,14 @@ PRAGMA_WARNING_DISABLE_VS(4355)
{ // LOCK: chunking
std::lock_guard send_guard{m_chunking_lock};
MDEBUG("do_send() will SPLIT into small chunks, from packet="<<message.size()<<" B for ptr="<<(void*)message.ptr.get());
while (!message.view.empty()) {
bool ok = do_send_chunk(message.extract_prefix(chunksize_good));
if (!ok) {
MDEBUG("do_send() DONE ***FAILED***");
MDEBUG("do_send() SEND was aborted in middle of big package - this is probably harmless (e.g. peer closed connection)");
return false; // partial failure in sending
}
}
MDEBUG("do_send() DONE SPLIT send");
MDEBUG("do_send() m_connection_type = " << m_connection_type);
return true; // done - e.g. queued - all the chunks of current do_send call
} // LOCK: chunking
} // a big block (to be chunked) - all chunks
@ -506,7 +469,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
context.m_current_speed_up = current_speed_up;
context.m_max_speed_up = std::max(context.m_max_speed_up, current_speed_up);
//MINFO("[sock " << socket().native_handle() << "] SEND " << cb);
context.m_last_send = std::chrono::steady_clock::now();
context.m_send_cnt += chunk.size();
//some data should be wrote to stream
@ -522,11 +484,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
{
retry++;
/* if ( ::cryptonote::core::get_is_stopping() ) { // TODO re-add fast stop
MDEBUG("ABORT queue wait due to stopping");
return false; // aborted
}*/
using engine = std::mt19937;
static bool initialized = false;
static engine rng;
@ -541,14 +498,11 @@ PRAGMA_WARNING_DISABLE_VS(4355)
}
int ms = std::uniform_int_distribution<>{250, 299}(rng);
MDEBUG("Sleeping because QUEUE is FULL, in " << __FUNCTION__ << " for " << ms << " ms before packet_size="<<chunk.size()); // XXX debug sleep
queue_lock.unlock();
std::this_thread::sleep_for(std::chrono::milliseconds{ms});
queue_lock.lock();
MDEBUG("sleep for queue: " << ms);
if (retry > retry_limit) {
MWARNING("send que size is more than ABSTRACT_SERVER_SEND_QUE_MAX_COUNT(" << ABSTRACT_SERVER_SEND_QUE_MAX_COUNT << "), shutting down connection");
shutdown();
return false;
}
@ -559,22 +513,18 @@ PRAGMA_WARNING_DISABLE_VS(4355)
if(m_send_que.size() > 1)
{ // active operation should be in progress, nothing to do, just wait last operation callback
auto size_now = m_send_que.back().size();
MDEBUG("do_send_chunk() NOW just queues: packet="<<size_now<<" B, is added to queue-size="<<m_send_que.size());
//do_send_handler_delayed( ptr , size_now ); // (((H))) // empty function
LOG_TRACE_CC(context, "[sock " << socket().native_handle() << "] Async send requested " << m_send_que.front().size());
}
else
{ // no active operation
if(m_send_que.size()!=1)
{
MERROR("Looks like no active operations, but send que size != 1!!");
return false;
}
auto size_now = m_send_que.front().size();
MDEBUG("do_send_chunk() NOW SENSD: packet="<<size_now<<" B");
if (speed_limit_is_enabled())
do_send_handler_write( m_send_que.back().data(), m_send_que.back().size() ); // (((H)))
@ -586,9 +536,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
boost::bind(&connection<t_protocol_handler>::handle_write, self, _1, _2)
)
);
//MTRACE("(chunk): " << size_now);
//logger_handle_net_write(size_now);
//MINFO("[sock " << socket().native_handle() << "] Async send requested " << m_send_que.front().size());
}
//do_send_handler_stop( ptr , cb ); // empty function
@ -629,10 +576,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
std::lock_guard lock{hosts_mutex};
static std::map<std::string, unsigned int> hosts;
unsigned int &val = hosts[host];
if (delta > 0)
MTRACE("New connection from host " << host << ": " << val);
else if (delta < 0)
MTRACE("Closed connection from host " << host << ": " << val);
CHECK_AND_ASSERT_THROW_MES(delta >= 0 || val >= (unsigned)-delta, "Count would go negative");
CHECK_AND_ASSERT_THROW_MES(delta <= 0 || val <= std::numeric_limits<unsigned int>::max() - (unsigned)delta, "Count would wrap");
val += delta;
@ -644,19 +587,15 @@ PRAGMA_WARNING_DISABLE_VS(4355)
{
if (ms < 0s)
{
MWARNING("Ignoring negative timeout " << ms.count());
return;
}
MTRACE((add ? "Adding" : "Setting") << " " << ms.count() << "ms expiry");
auto self = safe_shared_from_this();
if(!self)
{
MERROR("Resetting timer on a dead object");
return;
}
if (m_was_shutdown)
{
MERROR("Setting timer on a shut down object");
return;
}
if (add)
@ -670,7 +609,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
{
if(ec == boost::asio::error::operation_aborted)
return;
MDEBUG(context << "connection timeout, closing");
self->close();
});
}
@ -703,7 +641,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
auto self = safe_shared_from_this();
if(!self)
return false;
//MINFO("[sock " << socket().native_handle() << "] Que Shutdown called.");
m_timer.cancel();
size_t send_que_size = 0;
{
@ -739,11 +676,9 @@ PRAGMA_WARNING_DISABLE_VS(4355)
void connection<t_protocol_handler>::handle_write(const boost::system::error_code& e, size_t cb)
{
TRY_ENTRY();
LOG_TRACE_CC(context, "[sock " << socket().native_handle() << "] Async send calledback " << cb);
if (e)
{
MDEBUG("[sock " << socket().native_handle() << "] Some problems at write: " << e.message() << ':' << e.value());
shutdown();
return;
}
@ -758,7 +693,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
std::unique_lock lock{m_send_que_lock};
if(m_send_que.empty())
{
MERROR("[sock " << socket().native_handle() << "] m_send_que.size() == 0 at handle_write!");
return;
}
@ -774,7 +708,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
//have more data to send
reset_timer(get_default_timeout(), false);
auto size_now = m_send_que.front().size();
MDEBUG("handle_write() NOW SENDS: packet="<<size_now<<" B" <<", from queue size="<<m_send_que.size());
if (speed_limit_is_enabled())
do_send_handler_write_from_queue(e, m_send_que.front().size() , m_send_que.size()); // (((H)))
CHECK_AND_ASSERT_MES( size_now == m_send_que.front().size(), void(), "Unexpected queue size");
@ -784,7 +717,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
boost::bind(&connection<t_protocol_handler>::handle_write, connection<t_protocol_handler>::shared_from_this(), _1, _2)
)
);
//MTRACE("(normal)" << size_now);
}
lock.unlock();
@ -800,10 +732,8 @@ PRAGMA_WARNING_DISABLE_VS(4355)
void connection<t_protocol_handler>::setRpcStation()
{
m_connection_type = e_connection_type_RPC;
MDEBUG("set m_connection_type = RPC ");
}
template<class t_protocol_handler>
bool connection<t_protocol_handler>::speed_limit_is_enabled() const {
return m_connection_type != e_connection_type_RPC ;
@ -893,7 +823,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
acceptor_.listen();
boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_.local_endpoint();
m_port = binded_endpoint.port();
MDEBUG("start accept (IPv4)");
new_connection_.reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type));
acceptor_.async_accept(new_connection_->socket(),
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept_ipv4, this,
@ -906,7 +835,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
if (ipv4_failed != "")
{
MERROR("Failed to bind IPv4: " << ipv4_failed);
if (require_ipv4)
{
throw std::runtime_error("Failed to bind IPv4 (set to required)");
@ -930,7 +858,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
acceptor_ipv6.listen();
boost::asio::ip::tcp::endpoint binded_endpoint = acceptor_ipv6.local_endpoint();
m_port_ipv6 = binded_endpoint.port();
MDEBUG("start accept (IPv6)");
new_connection_ipv6.reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type));
acceptor_ipv6.async_accept(new_connection_ipv6->socket(),
boost::bind(&boosted_tcp_server<t_protocol_handler>::handle_accept_ipv6, this,
@ -944,7 +871,6 @@ PRAGMA_WARNING_DISABLE_VS(4355)
if (use_ipv6 && ipv6_failed != "")
{
MERROR("Failed to bind IPv6: " << ipv6_failed);
if (ipv4_failed != "")
{
throw std::runtime_error("Failed to bind IPv4 and IPv6");
@ -955,12 +881,12 @@ PRAGMA_WARNING_DISABLE_VS(4355)
}
catch (const std::exception &e)
{
MFATAL("Error starting server: " << e.what());
throw std::runtime_error(std::string("Error starting server: {}") + e.what());
return false;
}
catch (...)
{
MFATAL("Error starting server");
throw std::runtime_error("Error starting server");
return false;
}
}
@ -975,12 +901,10 @@ DISABLE_GCC_WARNING(maybe-uninitialized)
uint32_t p_ipv6 = 0;
if (port.size() && !string_tools::get_xtype_from_string(p, port)) {
MERROR("Failed to convert port no = " << port);
return false;
}
if (port_ipv6.size() && !string_tools::get_xtype_from_string(p_ipv6, port_ipv6)) {
MERROR("Failed to convert port no = " << port_ipv6);
return false;
}
return this->init_server(p, address, p_ipv6, address_ipv6, use_ipv6, require_ipv4);
@ -991,11 +915,6 @@ POP_WARNINGS
bool boosted_tcp_server<t_protocol_handler>::worker_thread()
{
TRY_ENTRY();
uint32_t local_thr_index = m_thread_index++;
std::string thread_name = std::string("[") + m_thread_name_prefix;
thread_name += std::to_string(local_thr_index) + "]";
MLOG_SET_THREAD_NAME(thread_name);
// MDEBUG("Thread name: " << m_thread_name_prefix);
while(!m_stop_signal_sent)
{
try
@ -1003,16 +922,10 @@ POP_WARNINGS
io_service_.run();
return true;
}
catch(const std::exception& ex)
{
MERROR("Exception at server worker thread, what=" << ex.what());
}
catch(...)
{
MERROR("Exception at server worker thread, unknown execption");
}
}
//MINFO("Worker thread finished");
return true;
CATCH_ENTRY_L0("boosted_tcp_server<t_protocol_handler>::worker_thread", false);
}
@ -1024,7 +937,6 @@ POP_WARNINGS
auto it = server_type_map.find(m_thread_name_prefix);
if (it==server_type_map.end()) throw std::runtime_error("Unknown prefix/server type:" + std::string(prefix_name));
auto connection_type = it->second; // the value of type
MINFO("Set server type to: " << connection_type << " from name: " << m_thread_name_prefix << ", prefix_name = " << prefix_name);
}
//---------------------------------------------------------------------------------
template<class t_protocol_handler>
@ -1040,7 +952,6 @@ POP_WARNINGS
TRY_ENTRY();
m_threads_count = threads_count;
m_main_thread_id = std::this_thread::get_id();
MLOG_SET_THREAD_NAME("[SRV_MAIN]");
while(!m_stop_signal_sent)
{
@ -1050,36 +961,28 @@ POP_WARNINGS
for (std::size_t i = 0; i < threads_count; ++i)
{
m_threads.emplace_back([this] { worker_thread(); });
MDEBUG("Run server thread name: " << m_thread_name_prefix);
}
}
// Wait for all threads in the pool to exit.
if (wait)
{
MDEBUG("JOINING all threads");
for (auto& th: m_threads)
th.join();
MDEBUG("JOINING all threads - almost");
m_threads.clear();
MDEBUG("JOINING all threads - DONE");
}
else {
MDEBUG("Reiniting OK.");
return true;
}
if(wait && !m_stop_signal_sent)
{
//some problems with the listening socket ?..
MDEBUG("Net service stopped without stop request, restarting...");
if(!this->init_server(m_port, m_address, m_port_ipv6, m_address_ipv6, m_use_ipv6, m_require_ipv4))
{
MDEBUG("Reiniting service failed, exit.");
return false;
}else
{
MDEBUG("Reiniting OK.");
//}else
//{
}
}
}
@ -1145,8 +1048,6 @@ POP_WARNINGS
template<class t_protocol_handler>
void boosted_tcp_server<t_protocol_handler>::handle_accept(const boost::system::error_code& e, bool ipv6)
{
MDEBUG("handle_accept");
boost::asio::ip::tcp::acceptor* current_acceptor = &acceptor_;
connection_ptr* current_new_connection = &new_connection_;
auto accept_function_pointer = &boosted_tcp_server<t_protocol_handler>::handle_accept_ipv4;
@ -1162,7 +1063,6 @@ POP_WARNINGS
if (!e)
{
if (m_connection_type == e_connection_type_RPC) {
MDEBUG("New server for RPC connections");
(*current_new_connection)->setRpcStation(); // hopefully this is not needed actually
}
connection_ptr conn(std::move((*current_new_connection)));
@ -1187,19 +1087,13 @@ POP_WARNINGS
conn->save_dbg_log();
return;
}
else
{
MERROR("Error in boosted_tcp_server<t_protocol_handler>::handle_accept: " << e);
}
}
catch (const std::exception &e)
{
MERROR("Exception in boosted_tcp_server<t_protocol_handler>::handle_accept: " << e.what());
}
// error path, if e or exception
assert(m_state != nullptr); // always set in constructor
MERROR("Some problems at accept: " << e.message() << ", connections_count = " << m_state->sock_count);
std::this_thread::sleep_for(100ms);
(*current_new_connection).reset(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type));
current_acceptor->async_accept((*current_new_connection)->socket(),
@ -1220,10 +1114,6 @@ POP_WARNINGS
return true;
}
}
else
{
MWARNING(out << " was not added, socket/io_service mismatch");
}
return false;
}
//---------------------------------------------------------------------------------
@ -1240,7 +1130,6 @@ POP_WARNINGS
sock_.bind(local_endpoint, ec);
if (ec)
{
MERROR("Error binding to " << bind_ip << ": " << ec.message());
if (sock_.is_open())
sock_.close();
return CONNECT_FAILURE;
@ -1284,7 +1173,6 @@ POP_WARNINGS
{
//timeout
sock_.close();
MTRACE("Failed to connect to " << adr << ":" << port << ", because of timeout (" << conn_timeout << ")");
return CONNECT_FAILURE;
}
}
@ -1292,14 +1180,11 @@ POP_WARNINGS
if (ec || !sock_.is_open())
{
MTRACE("Some problems at connect, message: " << ec.message());
if (sock_.is_open())
sock_.close();
return CONNECT_FAILURE;
}
MTRACE("Connected success to " << adr << ':' << port);
return CONNECT_SUCCESS;
CATCH_ENTRY_L0("boosted_tcp_server<t_protocol_handler>::try_connect", CONNECT_FAILURE);
@ -1313,7 +1198,6 @@ POP_WARNINGS
connection_ptr new_connection_l(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type) );
connections_mutex.lock();
connections_.insert(new_connection_l);
MDEBUG("connections_ size now " << connections_.size());
connections_mutex.unlock();
auto scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ std::lock_guard lock{connections_mutex}; connections_.erase(new_connection_l); });
boost::asio::ip::tcp::socket& sock_ = new_connection_l->socket();
@ -1350,13 +1234,11 @@ POP_WARNINGS
{
if (!m_use_ipv6)
{
MERROR("Failed to resolve " << adr);
return false;
}
else
{
try_ipv6 = true;
MINFO("Resolving address as IPv4 failed, trying IPv6");
}
}
else
@ -1372,7 +1254,6 @@ POP_WARNINGS
if(iterator == end)
{
MERROR("Failed to resolve " << adr);
return false;
}
else
@ -1390,9 +1271,6 @@ POP_WARNINGS
}
MDEBUG("Trying to connect to " << adr << ":" << port << ", bind_ip = " << bind_ip_to_use);
//boost::asio::ip::tcp::endpoint remote_endpoint(boost::asio::ip::address::from_string(addr.c_str()), port);
boost::asio::ip::tcp::endpoint remote_endpoint(*iterator);
auto try_connect_result = try_connect(new_connection_l, adr, port, sock_, remote_endpoint, bind_ip_to_use, conn_timeout);
@ -1412,7 +1290,6 @@ POP_WARNINGS
else
{
assert(m_state != nullptr); // always set in constructor
MERROR("[sock " << new_connection_l->socket().native_handle() << "] Failed to start connection, connections_count = " << m_state->sock_count);
}
new_connection_l->save_dbg_log();
@ -1429,7 +1306,6 @@ POP_WARNINGS
connection_ptr new_connection_l(new connection<t_protocol_handler>(io_service_, m_state, m_connection_type) );
connections_mutex.lock();
connections_.insert(new_connection_l);
MDEBUG("connections_ size now " << connections_.size());
connections_mutex.unlock();
auto scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ std::lock_guard lock{connections_mutex}; connections_.erase(new_connection_l); });
boost::asio::ip::tcp::socket& sock_ = new_connection_l->socket();
@ -1465,13 +1341,8 @@ POP_WARNINGS
{
if (!try_ipv6)
{
MERROR("Failed to resolve " << adr);
return false;
}
else
{
MINFO("Resolving address as IPv4 failed, trying IPv6");
}
}
if (try_ipv6)
@ -1482,7 +1353,6 @@ POP_WARNINGS
if(iterator == end)
{
MERROR("Failed to resolve " << adr);
return false;
}
}
@ -1498,7 +1368,6 @@ POP_WARNINGS
sock_.bind(local_endpoint, ec);
if (ec)
{
MERROR("Error binding to " << bind_ip << ": " << ec.message());
if (sock_.is_open())
sock_.close();
return false;
@ -1512,7 +1381,6 @@ POP_WARNINGS
{
if(error != boost::asio::error::operation_aborted)
{
MTRACE("Failed to connect to " << adr << ':' << port << ", because of timeout (" << conn_timeout << ")");
new_connection_l->socket().close();
}
});
@ -1520,8 +1388,6 @@ POP_WARNINGS
sock_.async_connect(remote_endpoint, [=](const boost::system::error_code& ec_)
{
t_connection_context conn_context{};
boost::system::error_code ignored_ec;
boost::asio::ip::tcp::socket::endpoint_type lep = new_connection_l->socket().local_endpoint(ignored_ec);
if(!ec_)
{//success
if(!sh_deadline->cancel())
@ -1529,9 +1395,6 @@ POP_WARNINGS
cb(conn_context, boost::asio::error::operation_aborted);//this mean that deadline timer already queued callback with cancel operation, rare situation
}else
{
MTRACE("[sock " << new_connection_l->socket().native_handle() << "] Connected success to " << adr << ':' << port <<
" from " << lep.address().to_string() << ':' << lep.port());
// start adds the connection to the config object's list, so we don't need to have it locally anymore
connections_mutex.lock();
connections_.erase(new_connection_l);
@ -1544,14 +1407,11 @@ POP_WARNINGS
}
else
{
MTRACE("[sock " << new_connection_l->socket().native_handle() << "] Failed to start connection to " << adr << ':' << port);
cb(conn_context, boost::asio::error::fault);
}
}
}else
{
MTRACE("[sock " << new_connection_l->socket().native_handle() << "] Failed to connect to " << adr << ':' << port <<
" from " << lep.address().to_string() << ':' << lep.port() << ": " << ec_.message() << ':' << ec_.value());
cb(conn_context, ec_);
}
});

View File

@ -32,10 +32,6 @@
#include "../misc_log_ex.h"
#include "../span.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "net.buffer"
//#define NET_BUFFER_LOG(x) MDEBUG(x)
#define NET_BUFFER_LOG(x) ((void)0)
namespace epee

View File

@ -33,9 +33,6 @@
#include "levin_base.h"
#include "../int-util.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "net"
namespace epee
{
namespace levin
@ -91,7 +88,6 @@ namespace levin
{
if(!m_config.m_pcommands_handler)
{
LOG_ERROR_CC(m_conn_context, "Command handler not set!");
return false;
}
m_cach_in_buffer.append((const char*)ptr, cb);
@ -106,7 +102,6 @@ namespace levin
{
if(m_cach_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cach_in_buffer.data()) != SWAP64LE(LEVIN_SIGNATURE))
{
LOG_ERROR_CC(m_conn_context, "Signature mismatch on accepted connection");
return false;
}
is_continue = false;
@ -126,7 +121,6 @@ namespace levin
#endif
if(LEVIN_SIGNATURE != phead.m_signature)
{
LOG_ERROR_CC(m_conn_context, "Signature mismatch on accepted connection");
return false;
}
m_current_head = phead;
@ -169,7 +163,6 @@ namespace levin
m_state = conn_state_reading_head;
break;
default:
LOG_ERROR_CC(m_conn_context, "Undefined state in levin_server_impl::connection_handler, m_state=" << m_state);
return false;
}
}

View File

@ -32,6 +32,7 @@
#include <atomic>
#include <memory>
#include <thread>
#include "levin_base.h"
#include "buffer.h"
@ -41,9 +42,6 @@
#include <random>
#include <chrono>
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "net"
#ifndef MIN_BYTES_WANTED
#define MIN_BYTES_WANTED 512
#endif
@ -135,11 +133,6 @@ class async_protocol_handler
if(!m_pservice_endpoint->do_send(shared_sv{std::move(data)}))
return false;
MDEBUG(m_connection_context << "LEVIN_PACKET_SENT. [len=" << head.m_cb
<< ", flags" << head.m_flags
<< ", r?=" << head.m_have_to_return_data
<<", cmd = " << head.m_command
<< ", ver=" << head.m_protocol_version);
return true;
}
@ -194,13 +187,11 @@ public:
{
if(m_con.start_outer_call())
{
MDEBUG(con.get_context_ref() << "anvoke_handler, timeout: " << timeout.count());
m_timer.expires_from_now(std::chrono::milliseconds(timeout));
m_timer.async_wait([&con, command, cb, timeout](const boost::system::error_code& ec)
{
if(ec == boost::asio::error::operation_aborted)
return;
MINFO(con.get_context_ref() << "Timeout on invoke operation happened, command: " << command << " timeout: " << timeout.count());
epee::span<const uint8_t> fake;
cb(LEVIN_ERROR_CONNECTION_TIMEDOUT, fake, con.get_context_ref());
con.close();
@ -263,7 +254,6 @@ public:
{
if(ec == boost::asio::error::operation_aborted)
return;
MINFO(con.get_context_ref() << "Timeout on invoke operation happened, command: " << command << " timeout: " << timeout.count());
epee::span<const uint8_t> fake;
cb(LEVIN_ERROR_CONNECTION_TIMEDOUT, fake, con.get_context_ref());
con.close();
@ -282,7 +272,6 @@ public:
std::lock_guard lock{m_invoke_response_handlers_lock};
if (m_protocol_released)
{
MERROR("Adding response handler to a released object");
return false;
}
std::shared_ptr<invoke_response_handler_base> handler(std::make_shared<anvoke_handler<callback_t>>(cb, timeout, con, command));
@ -325,20 +314,14 @@ public:
{
std::this_thread::sleep_for(100ms);
}
CHECK_AND_ASSERT_MES_NO_RET(0 == m_wait_count, "Failed to wait for operation completion. m_wait_count = " << m_wait_count);
MTRACE(m_connection_context << "~async_protocol_handler()");
}
catch (...) { /* ignore */ }
}
bool start_outer_call()
{
MTRACE(m_connection_context << "[levin_protocol] -->> start_outer_call");
if(!m_pservice_endpoint->add_ref())
{
MERROR(m_connection_context << "[levin_protocol] -->> start_outer_call failed");
return false;
}
m_wait_count++;
@ -346,7 +329,6 @@ public:
}
bool finish_outer_call()
{
MTRACE(m_connection_context << "[levin_protocol] <<-- finish_outer_call");
m_wait_count--;
m_pservice_endpoint->release();
return true;
@ -403,7 +385,6 @@ public:
if(!m_config.m_pcommands_handler)
{
MERROR(m_connection_context << "Commands handler not set!");
return false;
}
@ -414,9 +395,6 @@ public:
// flipped to subtraction; prevent overflow since m_max_packet_size is variable and public
if(cb > m_config.m_max_packet_size - m_cache_in_buffer.size() - m_fragment_buffer.size())
{
MWARNING(m_connection_context << "Maximum packet size exceed!, m_max_packet_size = " << m_config.m_max_packet_size
<< ", packet received " << m_cache_in_buffer.size() + cb
<< ", connection will be closed.");
return false;
}
@ -439,7 +417,6 @@ public:
//async call scenario
std::shared_ptr<invoke_response_handler_base> response_handler = m_invoke_response_handlers.front();
response_handler->reset_timer();
MDEBUG(m_connection_context << "LEVIN_PACKET partial msg received. len=" << cb);
}
}
break;
@ -467,7 +444,6 @@ public:
if (m_fragment_buffer.size() < sizeof(bucket_head2))
{
MERROR(m_connection_context << "Fragmented data too small for levin header");
return false;
}
@ -479,12 +455,6 @@ public:
bool is_response = (m_oponent_protocol_ver == LEVIN_PROTOCOL_VER_1 && m_current_head.m_flags&LEVIN_PACKET_RESPONSE);
MDEBUG(m_connection_context << "LEVIN_PACKET_RECEIVED. [len=" << m_current_head.m_cb
<< ", flags" << m_current_head.m_flags
<< ", r?=" << m_current_head.m_have_to_return_data
<<", cmd = " << m_current_head.m_command
<< ", v=" << m_current_head.m_protocol_version);
if(is_response)
{//response to some invoke
@ -507,7 +477,6 @@ public:
//use sync call scenario
if(m_wait_count == 0 && m_close_called == 0)
{
MERROR(m_connection_context << "no active invoke when response came, wtf?");
return false;
}else
{
@ -533,12 +502,6 @@ public:
if(!m_pservice_endpoint->do_send(shared_sv{std::move(return_buff)}))
return false;
MDEBUG(m_connection_context << "LEVIN_PACKET_SENT. [len=" << head.m_cb
<< ", flags" << head.m_flags
<< ", r?=" << head.m_have_to_return_data
<<", cmd = " << head.m_command
<< ", ver=" << head.m_protocol_version);
}
else
m_config.m_pcommands_handler->notify(m_current_head.m_command, buff_to_invoke, m_connection_context);
@ -557,7 +520,6 @@ public:
{
if(m_cache_in_buffer.size() >= sizeof(uint64_t) && *((uint64_t*)m_cache_in_buffer.span(8).data()) != SWAP64LE(LEVIN_SIGNATURE))
{
MWARNING(m_connection_context << "Signature mismatch, connection will be closed");
return false;
}
is_continue = false;
@ -577,7 +539,6 @@ public:
#endif
if(LEVIN_SIGNATURE != phead.m_signature)
{
LOG_ERROR_CC(m_connection_context, "Signature mismatch, connection will be closed");
return false;
}
m_current_head = phead;
@ -587,15 +548,11 @@ public:
m_oponent_protocol_ver = m_current_head.m_protocol_version;
if(m_current_head.m_cb > m_config.m_max_packet_size)
{
LOG_ERROR_CC(m_connection_context, "Maximum packet size exceed!, m_max_packet_size = " << m_config.m_max_packet_size
<< ", packet header received " << m_current_head.m_cb
<< ", connection will be closed.");
return false;
}
}
break;
default:
LOG_ERROR_CC(m_connection_context, "Undefined state in levin_server_impl::connection_handler, m_state=" << m_state);
return false;
}
}
@ -645,7 +602,6 @@ public:
if(!send_message(command, in_buff, LEVIN_PACKET_REQUEST, true))
{
LOG_ERROR_CC(m_connection_context, "Failed to do_send");
err_code = LEVIN_ERROR_CONNECTION;
break;
}
@ -686,7 +642,6 @@ public:
if (!send_message(command, in_buff, LEVIN_PACKET_REQUEST, true))
{
LOG_ERROR_CC(m_connection_context, "Failed to send request");
return LEVIN_ERROR_CONNECTION;
}
@ -702,7 +657,6 @@ public:
}
if (std::chrono::steady_clock::now() > start + m_config.m_invoke_timeout)
{
MWARNING(m_connection_context << "invoke timeout (" << m_config.m_invoke_timeout.count() << "), closing connection ");
close();
return LEVIN_ERROR_CONNECTION_TIMEDOUT;
}
@ -735,7 +689,6 @@ public:
if (!send_message(command, in_buff, LEVIN_PACKET_REQUEST, false))
{
LOG_ERROR_CC(m_connection_context, "Failed to send notify message");
return -1;
}
@ -759,11 +712,9 @@ public:
const std::size_t length = message.view.size();
if (!m_pservice_endpoint->do_send(std::move(message)))
{
LOG_ERROR_CC(m_connection_context, "Failed to send message, dropping it");
return -1;
}
MDEBUG(m_connection_context << "LEVIN_PACKET_SENT. [len=" << (length - sizeof(bucket_head2)) << ", r?=0]");
return 1;
}
//------------------------------------------------------------------------------------------
@ -809,7 +760,6 @@ void async_protocol_handler_config<t_connection_context>::delete_connections(siz
}
catch (const std::out_of_range &e)
{
MWARNING("Connection not found in m_connects, continuing");
}
--count;
}

View File

@ -437,36 +437,15 @@ namespace net_utils
//some helpers
std::string print_connection_context(const connection_context_base& ctx);
std::string print_connection_context_short(const connection_context_base& ctx);
inline MAKE_LOGGABLE(connection_context_base, ct, os)
{
os << "[" << epee::net_utils::print_connection_context_short(ct) << "] ";
return os;
}
inline std::ostream& operator<<(std::ostream& os, const connection_context_base& ct)
{
os << "[" << epee::net_utils::print_connection_context_short(ct) << "] ";
return os;
}
#define LOG_ERROR_CC(ct, message) MERROR(ct << message)
#define LOG_WARNING_CC(ct, message) MWARNING(ct << message)
#define LOG_INFO_CC(ct, message) MINFO(ct << message)
#define LOG_DEBUG_CC(ct, message) MDEBUG(ct << message)
#define LOG_TRACE_CC(ct, message) MTRACE(ct << message)
#define LOG_CC(level, ct, message) MLOG(level, ct << message)
#define LOG_PRINT_CC_L0(ct, message) LOG_PRINT_L0(ct << message)
#define LOG_PRINT_CC_L1(ct, message) LOG_PRINT_L1(ct << message)
#define LOG_PRINT_CC_L2(ct, message) LOG_PRINT_L2(ct << message)
#define LOG_PRINT_CC_L3(ct, message) LOG_PRINT_L3(ct << message)
#define LOG_PRINT_CC_L4(ct, message) LOG_PRINT_L4(ct << message)
#define LOG_PRINT_CCONTEXT_L0(message) LOG_PRINT_CC_L0(context, message)
#define LOG_PRINT_CCONTEXT_L1(message) LOG_PRINT_CC_L1(context, message)
#define LOG_PRINT_CCONTEXT_L2(message) LOG_PRINT_CC_L2(context, message)
#define LOG_PRINT_CCONTEXT_L3(message) LOG_PRINT_CC_L3(context, message)
#define LOG_ERROR_CCONTEXT(message) LOG_ERROR_CC(context, message)
#define CHECK_AND_ASSERT_MES_CC(condition, return_val, err_message) CHECK_AND_ASSERT_MES(condition, return_val, "[" << epee::net_utils::print_connection_context_short(context) << "]" << err_message)
}

View File

@ -29,10 +29,6 @@
#include "../misc_log_ex.h"
#include "keyvalue_serialization_overloads.h"
#include "../storages/portable_storage.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "serialization"
namespace epee
{
/************************************************************************/
@ -66,8 +62,7 @@ public: \
bool Class::load(epee::serialization::portable_storage& st, epee::serialization::section* parent_section) \
{ \
try { return _load(st, parent_section); } \
catch (const std::exception& err) { LOG_ERROR("Deserialization exception: " << err.what()); } \
catch (...) { LOG_ERROR("Unknown deserialization exception"); } \
catch (...) {} \
return false; \
} \
template <bool is_store> \
@ -98,7 +93,6 @@ public: \
catch(const std::exception& err) \
{ \
(void)(err); \
LOG_ERROR("Exception on deserializing: " << err.what());\
return false; \
}\
}\

View File

@ -34,6 +34,7 @@
#include <deque>
#include <array>
#include <optional>
#include <cstring>
#include "../span.h"
#include "../storages/portable_storage_base.h"
@ -152,7 +153,6 @@ namespace epee
return true;
} catch (const std::out_of_range&) { // ignore silently
} catch (const std::exception& e) {
LOG_ERROR("Failed to deserialize stl container: " << e.what());
}
return false;
}

View File

@ -30,9 +30,6 @@
#include "../span.h"
#include "../net/levin_base.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "net"
namespace epee
{
namespace net_utils
@ -51,13 +48,11 @@ namespace epee
int res = transport.invoke(command, buff_to_send, buff_to_recv);
if( res <=0 )
{
MERROR("Failed to invoke command " << command << " return code " << res);
return false;
}
serialization::portable_storage stg_ret;
if(!stg_ret.load_from_binary(buff_to_recv))
{
LOG_ERROR("Failed to load_from_binary on command " << command);
return false;
}
return result_struct.load(stg_ret);
@ -77,7 +72,6 @@ namespace epee
int res = transport.notify(command, buff_to_send);
if(res <=0 )
{
LOG_ERROR("Failed to notify command " << command << " return code " << res);
return false;
}
return true;
@ -95,13 +89,11 @@ namespace epee
int res = transport.invoke(command, buff_to_send, buff_to_recv, conn_id);
if( res <=0 )
{
LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res);
return false;
}
typename serialization::portable_storage stg_ret;
if(!stg_ret.load_from_binary(buff_to_recv))
{
LOG_ERROR("Failed to load_from_binary on command " << command);
return false;
}
return result_struct.load(stg_ret);
@ -119,20 +111,17 @@ namespace epee
t_result result_struct{};
if( code <=0 )
{
LOG_PRINT_L1("Failed to invoke command " << command << " return code " << code);
cb(code, std::move(result_struct), context);
return false;
}
serialization::portable_storage stg_ret;
if(!stg_ret.load_from_binary(buff))
{
LOG_ERROR("Failed to load_from_binary on command " << command);
cb(LEVIN_ERROR_FORMAT, std::move(result_struct), context);
return false;
}
if (!result_struct.load(stg_ret))
{
LOG_ERROR("Failed to load result struct on command " << command);
cb(LEVIN_ERROR_FORMAT, std::move(result_struct), context);
return false;
}
@ -141,7 +130,6 @@ namespace epee
}, inv_timeout);
if( res <=0 )
{
LOG_PRINT_L1("Failed to invoke command " << command << " return code " << res);
return false;
}
return true;
@ -159,7 +147,6 @@ namespace epee
int res = transport.notify(command, epee::strspan<uint8_t>(buff_to_send), conn_id);
if(res <=0 )
{
MERROR("Failed to notify command " << command << " return code " << res);
return false;
}
return true;
@ -172,7 +159,6 @@ namespace epee
serialization::portable_storage strg;
if(!strg.load_from_binary(in_buff))
{
LOG_ERROR("Failed to load_from_binary in command " << command);
return -1;
}
t_in_type in_struct{};
@ -180,7 +166,6 @@ namespace epee
if (!in_struct.load(strg))
{
LOG_ERROR("Failed to load in_struct in command " << command);
return -1;
}
int res = cb(command, in_struct, out_struct, context);
@ -189,7 +174,6 @@ namespace epee
if(!strg_out.store_to_binary(buff_out))
{
LOG_ERROR("Failed to store_to_binary in command" << command);
return -1;
}
@ -202,13 +186,11 @@ namespace epee
serialization::portable_storage strg;
if(!strg.load_from_binary(in_buff))
{
LOG_ERROR("Failed to load_from_binary in notify " << command);
return -1;
}
t_in_type in_struct{};
if (!in_struct.load(strg))
{
LOG_ERROR("Failed to load in_struct in notify " << command);
return -1;
}
return cb(command, in_struct, context);
@ -294,7 +276,6 @@ namespace epee
#define END_INVOKE_MAP2() \
LOG_ERROR("Unknown command:" << command); \
return LEVIN_ERROR_CONNECTION_HANDLER_NOT_DEFINED; \
}
}

View File

@ -33,6 +33,7 @@
#include <vector>
#include <deque>
#include <cstdint>
#include <map>
#include "../misc_log_ex.h"
#include "../int-util.h"

View File

@ -398,14 +398,8 @@ namespace epee
run_handler(nullptr, it, buff_json.end(), stg, 0);
return true;
}
catch(const std::exception& ex)
{
MERROR("Failed to parse json, what: " << ex.what());
return false;
}
catch(...)
{
MERROR("Failed to parse json");
return false;
}
}

View File

@ -32,6 +32,7 @@
#include "portable_storage_base.h"
#include <oxenc/endian.h>
#include <oxenmq/variant.h>
#include <limits>
namespace epee
{

View File

@ -92,7 +92,6 @@ POP_WARNINGS
void operator()(const std::string& from, uint64_t& to)
{
MTRACE("Converting std::string to uint64_t. Source: " << from);
const auto* strend = from.data() + from.size();
if (auto [p, ec] = std::from_chars(from.data(), strend, to); ec == std::errc{} && p == strend)
return; // Good: successfully consumed the whole string.

View File

@ -32,7 +32,6 @@ add_library(epee
levin_base.cpp
memwipe.c
mlocker.cpp
mlog.cpp
net_utils_base.cpp
network_throttle.cpp
network_throttle-detail.cpp
@ -63,7 +62,6 @@ endif()
target_link_libraries(epee
PUBLIC
easylogging
oxenmq::oxenmq
oxenc::oxenc
PRIVATE

View File

@ -137,8 +137,6 @@ connection_basic::connection_basic(boost::asio::ip::tcp::socket&& sock, std::sha
std::string remote_addr_str = "?";
try { boost::system::error_code e; remote_addr_str = socket_.remote_endpoint(e).address().to_string(); } catch(...){} ;
MDEBUG("Spawned connection #"<<mI->m_peer_number<<" to " << remote_addr_str << " currently we have sockets count:" << m_state->sock_count);
}
connection_basic::connection_basic(boost::asio::io_service &io_service, std::shared_ptr<connection_basic_shared_state> state)
@ -159,8 +157,6 @@ connection_basic::connection_basic(boost::asio::io_service &io_service, std::sha
std::string remote_addr_str = "?";
try { boost::system::error_code e; remote_addr_str = socket().remote_endpoint(e).address().to_string(); } catch(...){} ;
MDEBUG("Spawned connection #"<<mI->m_peer_number<<" to " << remote_addr_str << " currently we have sockets count:" << m_state->sock_count);
}
connection_basic::~connection_basic() noexcept(false) {
@ -168,7 +164,6 @@ connection_basic::~connection_basic() noexcept(false) {
std::string remote_addr_str = "?";
try { boost::system::error_code e; remote_addr_str = socket().remote_endpoint(e).address().to_string(); } catch(...){} ;
MDEBUG("Destructing connection #"<<mI->m_peer_number << " to " << remote_addr_str);
}
void connection_basic::set_rate_up_limit(uint64_t limit) {
@ -221,7 +216,6 @@ void connection_basic::sleep_before_packet(size_t packet_size, int phase, int q
do
{ // rate limiting
if (m_was_shutdown) {
MDEBUG("m_was_shutdown - so abort sleep");
return;
}
@ -232,8 +226,7 @@ void connection_basic::sleep_before_packet(size_t packet_size, int phase, int q
delay *= 0.50;
if (delay > 0) {
long int ms = (long int)(delay * 1000);
MTRACE("Sleeping in " << __FUNCTION__ << " for " << ms << " ms before packet_size="<<packet_size); // debug sleep
long int ms = (long int)(delay * 1000);
std::this_thread::sleep_for(std::chrono::milliseconds{ms});
}
} while(delay > 0);
@ -247,13 +240,11 @@ void connection_basic::sleep_before_packet(size_t packet_size, int phase, int q
}
void connection_basic::do_send_handler_write(const void* ptr , size_t cb ) {
// No sleeping here; sleeping is done once and for all in connection<t_protocol_handler>::handle_write
MTRACE("handler_write (direct) - before ASIO write, for packet="<<cb<<" B (after sleep)");
// No sleeping here; sleeping is done once and for all in connection<t_protocol_handler>::handle_write
}
void connection_basic::do_send_handler_write_from_queue( const boost::system::error_code& e, size_t cb, int q_len ) {
// No sleeping here; sleeping is done once and for all in connection<t_protocol_handler>::handle_write
MTRACE("handler_write (after write, from queue="<<q_len<<") - before ASIO write, for packet="<<cb<<" B (after sleep)");
// No sleeping here; sleeping is done once and for all in connection<t_protocol_handler>::handle_write
}
void connection_basic::logger_handle_net_read(size_t size) { // network data read

View File

@ -45,9 +45,6 @@
#include <mutex>
#include <utility>
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "mlocker"
// did an mlock operation previously fail? we only
// want to log an error once and be done with it
static std::atomic<bool> previously_failed{ false };
@ -58,7 +55,6 @@ static size_t query_page_size()
long ret = sysconf(_SC_PAGESIZE);
if (ret <= 0)
{
MERROR("Failed to determine page size");
return 0;
}
return ret;
@ -72,8 +68,6 @@ static void do_lock(void *ptr, size_t len)
{
#if defined HAVE_MLOCK
int ret = mlock(ptr, len);
if (ret < 0 && !previously_failed.exchange(true))
MERROR("Error locking page at " << ptr << ": " << strerror(errno) << ", subsequent mlock errors will be silenced");
#else
#warning Missing do_lock implementation
#endif
@ -83,11 +77,6 @@ static void do_unlock(void *ptr, size_t len)
{
#if defined HAVE_MLOCK
int ret = munlock(ptr, len);
// check whether we previously failed, but don't set it, this is just
// to pacify the errors of mlock()ing failed, in which case unlocking
// is also not going to work of course
if (ret < 0 && !previously_failed.load())
MERROR("Error unlocking page at " << ptr << ": " << strerror(errno));
#else
#warning Missing implementation of page size detection
#endif
@ -214,11 +203,7 @@ namespace epee
{
#if defined(HAVE_MLOCK)
std::map<size_t, unsigned int>::iterator i = map().find(page);
if (i == map().end())
{
MERROR("Attempt to unlock unlocked page at " << (void*)(page * page_size));
}
else
if (i != map().end())
{
if (!--i->second)
{

View File

@ -1,494 +0,0 @@
// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of the Andrey N. Sabelnikov nor the
// names of its contributors may be used to endorse or promote products
// derived from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER BE LIABLE FOR ANY
// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
#ifndef _MLOG_H_
#define _MLOG_H_
#include <date/date.h>
#include <chrono>
#ifdef _WIN32
#include <windows.h>
#ifndef ENABLE_VIRTUAL_TERMINAL_PROCESSING
#define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
#endif
#endif
#include <ctime>
#include <atomic>
#include <boost/algorithm/string.hpp>
#include "epee/string_tools.h"
#include "epee/misc_log_ex.h"
#ifndef USE_GHC_FILESYSTEM
#include <filesystem>
namespace fs { using namespace std::filesystem; }
#else
#include <ghc/filesystem.hpp>
namespace fs = ghc::filesystem;
#endif
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "logging"
#define MLOG_BASE_FORMAT "%datetime{%Y-%M-%d %H:%m:%s.%g}\t%thread\t%level\t%logger\t%loc\t%msg"
#define MLOG_LOG(x) CINFO(el::base::Writer,el::base::DispatchAction::FileOnlyLog,OXEN_DEFAULT_LOG_CATEGORY) << x
using namespace epee;
std::string mlog_get_default_log_path(const char *default_filename)
{
std::string process_name = epee::string_tools::get_current_module_name();
std::string default_log_folder = epee::string_tools::get_current_module_folder();
std::string default_log_file = process_name;
std::string::size_type a = default_log_file.rfind('.');
if ( a != std::string::npos )
default_log_file.erase( a, default_log_file.size());
if ( ! default_log_file.empty() )
default_log_file += ".log";
else
default_log_file = default_filename;
return (fs::u8path(default_log_folder) / fs::u8path(default_log_file)).u8string();
}
static void mlog_set_common_prefix()
{
static const char * const expected_filename = "contrib/epee/src/mlog.cpp";
const char *path = __FILE__, *expected_ptr = strstr(path, expected_filename);
if (!expected_ptr)
return;
el::Loggers::setFilenameCommonPrefix(std::string(path, expected_ptr - path));
}
static const char *get_default_categories(int level)
{
const char *categories = "";
switch (level)
{
case 0:
categories = "*:WARNING,net:FATAL,net.http:FATAL,net.p2p:FATAL,net.cn:FATAL,global:INFO,verify:FATAL,serialization:FATAL,logging:INFO,msgwriter:INFO";
break;
case 1:
categories = "*:INFO,global:INFO,stacktrace:INFO,logging:INFO,msgwriter:INFO,perf.*:DEBUG";
break;
case 2:
categories = "*:DEBUG";
break;
case 3:
categories = "*:TRACE";
break;
case 4:
categories = "*:TRACE";
break;
default:
break;
}
return categories;
}
#ifdef WIN32
bool EnableVTMode()
{
// Set output mode to handle virtual terminal sequences
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
if (hOut == INVALID_HANDLE_VALUE)
{
return false;
}
DWORD dwMode = 0;
if (!GetConsoleMode(hOut, &dwMode))
{
return false;
}
dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
if (!SetConsoleMode(hOut, dwMode))
{
return false;
}
return true;
}
#endif
void mlog_configure(const std::string &filename_base, bool console, const std::size_t max_log_file_size, const std::size_t max_log_files)
{
el::Configurations c;
c.setGlobally(el::ConfigurationType::Filename, filename_base);
c.setGlobally(el::ConfigurationType::ToFile, "true");
const char *log_format = getenv("OXEN_LOG_FORMAT");
if (!log_format)
log_format = MLOG_BASE_FORMAT;
c.setGlobally(el::ConfigurationType::Format, log_format);
c.setGlobally(el::ConfigurationType::ToStandardOutput, console ? "true" : "false");
c.setGlobally(el::ConfigurationType::MaxLogFileSize, std::to_string(max_log_file_size));
el::Loggers::setDefaultConfigurations(c, true);
el::Loggers::addFlag(el::LoggingFlag::HierarchicalLogging);
el::Loggers::addFlag(el::LoggingFlag::CreateLoggerAutomatically);
el::Loggers::addFlag(el::LoggingFlag::DisableApplicationAbortOnFatalLog);
el::Loggers::addFlag(el::LoggingFlag::ColoredTerminalOutput);
el::Loggers::addFlag(el::LoggingFlag::StrictLogFileSizeCheck);
el::Helpers::installPreRollOutCallback([filename_base, max_log_files](const char *name, size_t){
std::string rname = filename_base + "-" + date::format("%Y-%m-%d-%H-%M-%S", std::chrono::system_clock::now());
int ret = rename(name, rname.c_str());
if (ret < 0)
{
// can't log a failure, but don't do the file removal below
return;
}
if (max_log_files != 0)
{
std::vector<fs::path> found_files;
const auto filename_base_path = fs::u8path(filename_base);
const auto parent_path = filename_base_path.has_parent_path() ? filename_base_path.parent_path() : fs::path(".");
for (const auto& p : fs::directory_iterator{parent_path})
{
const std::string filename = p.path().u8string();
if (filename.size() >= filename_base.size() && std::memcmp(filename.data(), filename_base.data(), filename_base.size()) == 0)
found_files.push_back(p.path());
}
if (found_files.size() >= max_log_files)
{
std::sort(found_files.begin(), found_files.end(), [](auto& a, auto& b) {
std::error_code ec;
return fs::last_write_time(a, ec) < fs::last_write_time(b, ec);
});
for (size_t i = 0; i <= found_files.size() - max_log_files; ++i)
{
std::error_code ec;
if (!fs::remove(found_files[i], ec))
MERROR("Failed to remove " << found_files[i] << ": " << ec.message());
}
}
}
});
mlog_set_common_prefix();
const char *loki_log = getenv("OXEN_LOGS");
if (!loki_log)
{
loki_log = get_default_categories(0);
}
mlog_set_log(loki_log);
#ifdef WIN32
EnableVTMode();
#endif
}
void mlog_set_categories(const char *categories)
{
std::string new_categories;
if (*categories)
{
if (*categories == '+')
{
++categories;
new_categories = mlog_get_categories();
if (*categories)
{
if (!new_categories.empty())
new_categories += ",";
new_categories += categories;
}
}
else if (*categories == '-')
{
++categories;
new_categories = mlog_get_categories();
std::vector<std::string> single_categories;
boost::split(single_categories, categories, boost::is_any_of(","), boost::token_compress_on);
for (const std::string &s: single_categories)
{
size_t pos = new_categories.find(s);
if (pos != std::string::npos)
new_categories = new_categories.erase(pos, s.size());
}
}
else
{
new_categories = categories;
}
}
el::Loggers::setCategories(new_categories.c_str(), true);
MLOG_LOG("New log categories: " << el::Loggers::getCategories());
}
std::string mlog_get_categories()
{
return el::Loggers::getCategories();
}
// maps epee style log level to new logging system
void mlog_set_log_level(int level)
{
const char *categories = get_default_categories(level);
mlog_set_categories(categories);
}
void mlog_set_log(const char *log)
{
long level;
char *ptr = NULL;
if (!*log)
{
mlog_set_categories(log);
return;
}
level = strtol(log, &ptr, 10);
if (ptr && *ptr)
{
// we can have a default level, eg, 2,foo:ERROR
if (*ptr == ',') {
std::string new_categories = std::string(get_default_categories(level)) + ptr;
mlog_set_categories(new_categories.c_str());
}
else {
mlog_set_categories(log);
}
}
else if (level >= 0 && level <= 4)
{
mlog_set_log_level(level);
}
else
{
MERROR("Invalid numerical log level: " << log);
}
}
namespace epee
{
bool is_stdout_a_tty()
{
static std::atomic<bool> initialized(false);
static std::atomic<bool> is_a_tty(false);
if (!initialized.load(std::memory_order_acquire))
{
#if defined(WIN32)
is_a_tty.store(0 != _isatty(_fileno(stdout)), std::memory_order_relaxed);
#else
is_a_tty.store(0 != isatty(fileno(stdout)), std::memory_order_relaxed);
#endif
initialized.store(true, std::memory_order_release);
}
return is_a_tty.load(std::memory_order_relaxed);
}
void set_console_color(int color, bool bright)
{
if (!is_stdout_a_tty())
return;
switch(color)
{
case console_color_default:
{
#ifdef WIN32
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE| (bright ? FOREGROUND_INTENSITY:0));
#else
if(bright)
std::cout << "\033[1;37m";
else
std::cout << "\033[0m";
#endif
}
break;
case console_color_white:
{
#ifdef WIN32
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | (bright ? FOREGROUND_INTENSITY:0));
#else
if(bright)
std::cout << "\033[1;37m";
else
std::cout << "\033[0;37m";
#endif
}
break;
case console_color_red:
{
#ifdef WIN32
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | (bright ? FOREGROUND_INTENSITY:0));
#else
if(bright)
std::cout << "\033[1;31m";
else
std::cout << "\033[0;31m";
#endif
}
break;
case console_color_green:
{
#ifdef WIN32
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h_stdout, FOREGROUND_GREEN | (bright ? FOREGROUND_INTENSITY:0));
#else
if(bright)
std::cout << "\033[1;32m";
else
std::cout << "\033[0;32m";
#endif
}
break;
case console_color_blue:
{
#ifdef WIN32
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h_stdout, FOREGROUND_BLUE | FOREGROUND_INTENSITY);//(bright ? FOREGROUND_INTENSITY:0));
#else
if(bright)
std::cout << "\033[1;34m";
else
std::cout << "\033[0;34m";
#endif
}
break;
case console_color_cyan:
{
#ifdef WIN32
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h_stdout, FOREGROUND_GREEN | FOREGROUND_BLUE | (bright ? FOREGROUND_INTENSITY:0));
#else
if(bright)
std::cout << "\033[1;36m";
else
std::cout << "\033[0;36m";
#endif
}
break;
case console_color_magenta:
{
#ifdef WIN32
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h_stdout, FOREGROUND_BLUE | FOREGROUND_RED | (bright ? FOREGROUND_INTENSITY:0));
#else
if(bright)
std::cout << "\033[1;35m";
else
std::cout << "\033[0;35m";
#endif
}
break;
case console_color_yellow:
{
#ifdef WIN32
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | (bright ? FOREGROUND_INTENSITY:0));
#else
if(bright)
std::cout << "\033[1;33m";
else
std::cout << "\033[0;33m";
#endif
}
break;
}
}
void reset_console_color() {
if (!is_stdout_a_tty())
return;
#ifdef WIN32
HANDLE h_stdout = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(h_stdout, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
#else
std::cout << "\033[0m";
std::cout.flush();
#endif
}
}
static bool mlog(el::Level level, const char *category, const char *format, va_list ap) noexcept
{
int size = 0;
char *p = NULL;
va_list apc;
bool ret = true;
/* Determine required size */
va_copy(apc, ap);
size = vsnprintf(p, size, format, apc);
va_end(apc);
if (size < 0)
return false;
size++; /* For '\0' */
p = (char*)malloc(size);
if (p == NULL)
return false;
size = vsnprintf(p, size, format, ap);
if (size < 0)
{
free(p);
return false;
}
try
{
/* TODO(loki): when pulling upstream epee changes change this to:
MCLOG(level, category, el::Color::Default, p);
*/
MCLOG(level, category, p);
}
catch(...)
{
ret = false;
}
free(p);
return ret;
}
#define DEFLOG(fun,lev) \
bool m##fun(const char *category, const char *fmt, ...) { va_list ap; va_start(ap, fmt); bool ret = mlog(el::Level::lev, category, fmt, ap); va_end(ap); return ret; }
DEFLOG(error, Error)
DEFLOG(warning, Warning)
DEFLOG(info, Info)
DEFLOG(debug, Debug)
DEFLOG(trace, Trace)
#undef DEFLOG
#endif //_MLOG_H_

View File

@ -133,8 +133,7 @@ void network_throttle::set_name(const std::string &name)
void network_throttle::set_target_speed( network_speed_kbps target )
{
m_target_speed = target * 1024;
MINFO("Setting LIMIT: " << target << " kbps");
m_target_speed = target * 1024;
}
network_speed_kbps network_throttle::get_target_speed()
@ -155,7 +154,6 @@ void network_throttle::tick()
// TODO optimize when moving few slots at once
while ( (!m_any_packet_yet) || (last_sample_time_slot < current_sample_time_slot))
{
MTRACE("Moving counter buffer by 1 second " << last_sample_time_slot << " < " << current_sample_time_slot << " (last time " << m_last_sample_time<<")");
// rotate buffer
m_history.push_front(packet_info());
if (! m_any_packet_yet)
@ -185,13 +183,6 @@ void network_throttle::_handle_trafic_exact(size_t packet_size, size_t orginal_s
std::ostringstream oss; oss << "["; for (auto sample: m_history) oss << sample.m_size << " "; oss << "]" << std::ends;
std::string history_str = oss.str();
MTRACE("Throttle " << m_name << ": packet of ~"<<packet_size<<"b " << " (from "<<orginal_size<<" b)"
<< " Speed AVG=" << std::setw(4) << ((long int)(cts .average/1024)) <<"[w="<<cts .window<<"]"
<< " " << std::setw(4) << ((long int)(cts2.average/1024)) <<"[w="<<cts2.window<<"]"
<<" / " << " Limit="<< ((long int)(m_target_speed/1024)) <<" KiB/sec "
<< " " << history_str
);
}
void network_throttle::handle_trafic_tcp(size_t packet_size)
@ -214,8 +205,6 @@ void network_throttle::logger_handle_net(const std::string &filename, double tim
std::fstream file;
file.open(filename.c_str(), std::ios::app | std::ios::out );
file.precision(6);
if(!file.is_open())
MWARNING("Can't open file " << filename);
file << static_cast<int>(time) << " " << static_cast<double>(size/1024) << "\n";
file.close();
}
@ -269,28 +258,13 @@ void network_throttle::calculate_times(size_t packet_size, calculate_times_struc
if (cts.delay>=0) cts.delay = 0; // no traffic in history so we will not wait
}
double Wgood=-1;
{ // how much data we recommend now to download
Wgood = the_window_size + 1;
cts.recomendetDataSize = M*cts.window - E;
}
if (dbg) {
std::ostringstream oss; oss << "["; for (auto sample: m_history) oss << sample.m_size << " "; oss << "]" << std::ends;
std::string history_str = oss.str();
MTRACE((cts.delay > 0 ? "SLEEP" : "")
<< "dbg " << m_name << ": "
<< "speed is A=" << std::setw(8) <<cts.average<<" vs "
<< "Max=" << std::setw(8) <<M<<" "
<< " so sleep: "
<< "D=" << std::setw(8) <<cts.delay<<" sec "
<< "E="<< std::setw(8) << E << " (Enow="<<std::setw(8)<<Enow<<") "
<< "M=" << std::setw(8) << M <<" W="<< std::setw(8) << cts.window << " "
<< "R=" << std::setw(8) << cts.recomendetDataSize << " Wgood" << std::setw(8) << Wgood << " "
<< "History: " << std::setw(8) << history_str << " "
<< "m_last_sample_time=" << std::setw(8) << m_last_sample_time
);
}
}

View File

@ -1,7 +1,4 @@
#include "epee/storages/parserse_base_utils.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "serialization"
#include <algorithm>
#include <string>
@ -99,7 +96,6 @@ void match_string2(const char*& star_end_string, const char* buf_end, std::strin
break;
default:
val.push_back(*it);
LOG_PRINT_L0("Unknown escape sequence :\"\\" << *it << "\"");
}
escape_mode = false;
}else if(*it == '"')

View File

@ -119,7 +119,6 @@ namespace epee {
m_root.m_entries.clear();
if(source.size() < sizeof(storage_block_header))
{
LOG_ERROR("portable_storage: wrong binary format, packet size = " << source.size() << " less than expected sizeof(storage_block_header)=" << sizeof(storage_block_header));
return false;
}
storage_block_header* pbuff = (storage_block_header*)source.data();
@ -127,12 +126,10 @@ namespace epee {
pbuff->m_signature_b != PORTABLE_STORAGE_SIGNATUREB
)
{
LOG_ERROR("portable_storage: wrong binary format - signature mismatch");
return false;
}
if(pbuff->m_ver != PORTABLE_STORAGE_FORMAT_VER)
{
LOG_ERROR("portable_storage: wrong binary format - unknown format ver = " << pbuff->m_ver);
return false;
}
TRY_ENTRY();

View File

@ -37,6 +37,7 @@
#include "epee/memwipe.h"
#include "epee/misc_log_ex.h"
#include "epee/wipeable_string.h"
#include <limits>
static constexpr const char hex[] = u8"0123456789abcdef";

View File

@ -2,7 +2,7 @@
CLANG_FORMAT_DESIRED_VERSION=11
TARGET_DIRS=(src/wallet3 src/sqlitedb)
TARGET_DIRS=(src/wallet3 src/sqlitedb src/logging)
binary=$(which clang-format-$CLANG_FORMAT_DESIRED_VERSION 2>/dev/null)
if [ $? -ne 0 ]; then

View File

@ -61,16 +61,15 @@ endmacro()
system_or_submodule(OXENC oxenc liboxenc>=1.0.3 oxen-encoding)
system_or_submodule(OXENMQ oxenmq liboxenmq>=1.2.12 oxen-mq)
system_or_submodule(FMT fmt fmt>=8.0.0 fmt)
add_subdirectory(db_drivers)
add_subdirectory(easylogging++ easyloggingpp)
add_subdirectory(randomx EXCLUDE_FROM_ALL)
add_subdirectory(date EXCLUDE_FROM_ALL)
set(JSON_BuildTests OFF CACHE INTERNAL "")
set(JSON_MultipleHeaders ON CACHE BOOL "") # Allows multi-header nlohmann use
add_subdirectory(nlohmann-json EXCLUDE_FROM_ALL)
add_subdirectory(oxen-logging)
# uSockets doesn't really have a proper build system (just a very simple Makefile) so build it
# ourselves.

View File

@ -1,61 +0,0 @@
# Copyright (c) 2014-2018, The Monero Project
#
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without modification, are
# permitted provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice, this list of
# conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice, this list
# of conditions and the following disclaimer in the documentation and/or other
# materials provided with the distribution.
#
# 3. Neither the name of the copyright holder nor the names of its contributors may be
# used to endorse or promote products derived from this software without specific
# prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
cmake_minimum_required(VERSION 3.5)
project(easylogging CXX)
add_library(easylogging
easylogging++.cc)
set_property(TARGET easylogging PROPERTY POSITION_INDEPENDENT_CODE ON)
set_property(TARGET easylogging PROPERTY CXX_STANDARD 11)
set_property(TARGET easylogging PROPERTY CXX_STANDARD_REQUIRED ON)
find_package(Threads)
find_package(Backtrace)
target_include_directories(easylogging PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}")
target_link_libraries(easylogging
PRIVATE
Threads::Threads
${Backtrace_LIBRARIES})
# GUI/libwallet install target
if (BUILD_GUI_DEPS)
if(IOS)
set(lib_folder lib-${ARCH})
target_compile_options(easylogging PUBLIC -fno-stack-check)
else()
set(lib_folder lib)
endif()
install(TARGETS easylogging
ARCHIVE DESTINATION ${lib_folder}
LIBRARY DESTINATION ${lib_folder})
endif()

View File

@ -1,17 +0,0 @@
#pragma once
#include <limits.h>
#define ELPP_THREAD_SAFE
#define ELPP_DEFAULT_LOG_FILE ""
#define ELPP_DISABLE_DEFAULT_CRASH_HANDLING
#define ELPP_NO_CHECK_MACROS
#define ELPP_WINSOCK2
#define ELPP_NO_DEBUG_MACROS
#define ELPP_UTC_DATETIME
#ifdef EASYLOGGING_CC
#if !(!defined __GLIBC__ || !defined __GNUC__ || defined __MINGW32__ || defined __MINGW64__ || defined __ANDROID__)
#define ELPP_FEATURE_CRASH_LOG
#endif
#endif

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1
external/fmt vendored

@ -1 +0,0 @@
Subproject commit d141cdbeb0fb422a3fb7173b285fd38e0d1772dc

1
external/oxen-logging vendored Submodule

@ -0,0 +1 @@
Subproject commit 98a8882c81aa046fbadc0571fcea7bf92ed20154

2
external/oxen-mq vendored

@ -1 +1 @@
Subproject commit a93c16af04eba58fba2bf7f5726c4669c290bd46
Subproject commit 0858dd278b91a899b69210088622ca6fa3bb0eed

View File

@ -53,6 +53,7 @@ add_subdirectory(ringct)
add_subdirectory(checkpoints)
add_subdirectory(cryptonote_basic)
add_subdirectory(cryptonote_core)
add_subdirectory(logging)
add_subdirectory(lmdb)
add_subdirectory(multisig)
add_subdirectory(net)

View File

@ -43,6 +43,7 @@ target_link_libraries(blockchain_db
lmdb
filesystem
Boost::thread
logging
extra)
target_compile_definitions(blockchain_db PRIVATE

View File

@ -40,12 +40,11 @@
#include "lmdb/db_lmdb.h"
#include <chrono>
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "blockchain.db"
namespace cryptonote
{
static auto logcat = oxen::log::Cat("blockchain.db");
const command_line::arg_descriptor<std::string> arg_db_sync_mode = {
"db-sync-mode"
, "Specify sync option, using format [safe|fast|fastest]:[sync|async]:[<nblocks_per_sync>[blocks]|<nbytes_per_sync>[bytes]]."
@ -85,7 +84,7 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair
{
// should only need to compute hash for miner transactions
tx_hash = get_transaction_hash(tx);
LOG_PRINT_L3("null tx_hash_ptr - needed to compute: " << tx_hash);
oxen::log::trace(logcat, "null tx_hash_ptr - needed to compute: {}", tx_hash);
}
else
{
@ -119,7 +118,7 @@ void BlockchainDB::add_transaction(const crypto::hash& blk_hash, const std::pair
}
else
{
LOG_PRINT_L1("Unsupported input type, removing key images and aborting transaction addition");
oxen::log::info(logcat, "Unsupported input type, removing key images and aborting transaction addition");
for (const txin_v& tx_input : tx.vin)
{
if (std::holds_alternative<txin_to_key>(tx_input))
@ -330,22 +329,21 @@ void BlockchainDB::reset_stats()
void BlockchainDB::show_stats()
{
LOG_PRINT_L1("\n"
<< "*********************************\n"
<< "num_calls: " << num_calls << "\n"
<< "time_blk_hash: " << tools::friendly_duration(time_blk_hash) << "\n"
<< "time_tx_exists: " << tools::friendly_duration(time_tx_exists) << "\n"
<< "time_add_block1: " << tools::friendly_duration(time_add_block1) << "\n"
<< "time_add_transaction: " << tools::friendly_duration(time_add_transaction) << "\n"
<< "time_commit1: " << tools::friendly_duration(time_commit1) << "\n"
<< "*********************************\n"
);
oxen::log::info(logcat, "\n*********************************\n \
num_calls: {}\n \
time_blk_hash: {}\n \
time_tx_exists: {}\n \
time_add_block1: {}\n \
time_add_transaction: {}\n \
time_commit1: {}\n \
*********************************\n",
num_calls, tools::friendly_duration(time_blk_hash), tools::friendly_duration(time_tx_exists), tools::friendly_duration(time_add_block1), tools::friendly_duration(time_add_transaction), tools::friendly_duration(time_commit1));
}
void BlockchainDB::fixup(cryptonote::network_type)
{
if (is_read_only()) {
LOG_PRINT_L1("Database is opened read only - skipping fixup check");
oxen::log::info(logcat, "Database is opened read only - skipping fixup check");
return;
}
@ -393,7 +391,7 @@ uint64_t BlockchainDB::get_tx_block_height(const crypto::hash &h) const
if (result == std::numeric_limits<uint64_t>::max())
{
std::string err = "tx_data_t with hash " + tools::type_to_hex(h) + " not found in db";
LOG_PRINT_L1(err);
oxen::log::info(logcat, "{}", err);
throw TX_DNE(std::move(err));
}
return result;

File diff suppressed because it is too large Load Diff

View File

@ -46,8 +46,8 @@ namespace cryptonote
LockedTXN(LockedTXN &&o) : m_db{o.m_db}, m_batch{o.m_batch} { o.m_batch = false; }
LockedTXN &operator=(LockedTXN &&) = delete;
void commit() { try { if (m_batch) { m_db.batch_stop(); m_batch = false; } } catch (const std::exception &e) { MWARNING("LockedTXN::commit filtering exception: " << e.what()); } }
void abort() { try { if (m_batch) { m_db.batch_abort(); m_batch = false; } } catch (const std::exception &e) { MWARNING("LockedTXN::abort filtering exception: " << e.what()); } }
void commit() { try { if (m_batch) { m_db.batch_stop(); m_batch = false; } } catch (const std::exception &e) { oxen::log::warning(globallogcat, "LockedTXN::commit filtering exception: {}", e.what()); } }
void abort() { try { if (m_batch) { m_db.batch_abort(); m_batch = false; } } catch (const std::exception &e) { oxen::log::warning(globallogcat, "LockedTXN::abort filtering exception: {}", e.what()); } }
~LockedTXN() { this->abort(); }
private:
BlockchainDB &m_db;

View File

@ -40,13 +40,12 @@
#include "common/string_util.h"
#include "cryptonote_basic/hardfork.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "blockchain.db.sqlite"
namespace cryptonote {
static auto logcat = oxen::log::Cat("blockchain.db.sqlite");
BlockchainSQLite::BlockchainSQLite(cryptonote::network_type nettype, fs::path db_path): db::Database(db_path, ""), m_nettype(nettype), filename {db_path.u8string()} {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{}", __func__);
height = 0;
if (!db.tableExists("batched_payments_accrued") || !db.tableExists("batched_payments_raw") || !db.tableExists("batch_db_info")) {
@ -59,7 +58,7 @@ namespace cryptonote {
}
void BlockchainSQLite::create_schema() {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{}", __func__);
auto& netconf = cryptonote::get_config(m_nettype);
@ -118,7 +117,7 @@ namespace cryptonote {
)",
netconf.BATCHING_INTERVAL));
MDEBUG("Database setup complete");
oxen::log::debug(logcat, "Database setup complete");
}
void BlockchainSQLite::upgrade_schema() {
@ -131,7 +130,7 @@ namespace cryptonote {
}
if (!have_offset) {
MINFO("Adding payout_offset to batching db");
oxen::log::info(logcat, "Adding payout_offset to batching db");
auto& netconf = get_config(m_nettype);
SQLite::Transaction transaction{
db,
@ -166,7 +165,7 @@ namespace cryptonote {
if (count != 0) {
constexpr auto error = "Batching db update to add offsets failed: not all addresses were converted";
MFATAL(error);
oxen::log::error(logcat, error);
throw std::runtime_error{error};
}
@ -175,7 +174,7 @@ namespace cryptonote {
}
void BlockchainSQLite::reset_database() {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{}", __func__);
db.exec(R"(
DROP TABLE IF EXISTS batched_payments_accrued;
@ -189,11 +188,11 @@ namespace cryptonote {
create_schema();
MDEBUG("Database reset complete");
oxen::log::debug(logcat, "Database reset complete");
}
void BlockchainSQLite::update_height(uint64_t new_height) {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__ << " Called with new height: " << new_height);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{} Called with new height: {}", __func__, new_height);
height = new_height;
prepared_exec(
"UPDATE batch_db_info SET height = ?",
@ -201,12 +200,12 @@ namespace cryptonote {
}
void BlockchainSQLite::increment_height() {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__ << " Called with height: " << height + 1);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{} Called with height: {}", __func__, height + 1);
update_height(height + 1);
}
void BlockchainSQLite::decrement_height() {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__ << " Called with height: " << height - 1);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{} Called with height: {}", __func__, height - 1);
update_height(height - 1);
}
@ -221,7 +220,7 @@ namespace cryptonote {
bool BlockchainSQLite::add_sn_rewards(const std::vector<cryptonote::batch_sn_payment>& payments) {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{}", __func__);
auto insert_payment = prepared_st(
"INSERT INTO batched_payments_accrued (address, payout_offset, amount) VALUES (?, ?, ?)"
" ON CONFLICT (address) DO UPDATE SET amount = amount + excluded.amount");
@ -232,8 +231,7 @@ namespace cryptonote {
auto offset = static_cast<int>(payment.address_info.address.modulus(netconf.BATCHING_INTERVAL));
auto amt = static_cast<int64_t>(payment.amount);
const auto& address_str = get_address_str(payment.address_info.address);
MTRACE(fmt::format("Adding record for SN reward contributor {} to database with amount {}",
address_str, amt));
oxen::log::trace(logcat, "Adding record for SN reward contributor {} to database with amount {}", address_str, amt);
db::exec_query(insert_payment, address_str, offset, amt);
insert_payment->reset();
}
@ -242,7 +240,7 @@ namespace cryptonote {
}
bool BlockchainSQLite::subtract_sn_rewards(const std::vector<cryptonote::batch_sn_payment>& payments) {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{}", __func__);
auto update_payment = prepared_st(
"UPDATE batched_payments_accrued SET amount = (amount - ?) WHERE address = ?");
@ -250,7 +248,7 @@ namespace cryptonote {
const auto& address_str = get_address_str(payment.address_info.address);
auto result = db::exec_query(update_payment, static_cast<int64_t>(payment.amount), address_str);
if (!result) {
MERROR("tried to subtract payment from an address that doesn't exist: " << address_str);
oxen::log::error(logcat, "tried to subtract payment from an address that doesn't exist: {}", address_str);
return false;
}
update_payment->reset();
@ -260,7 +258,7 @@ namespace cryptonote {
}
std::vector<cryptonote::batch_sn_payment> BlockchainSQLite::get_sn_payments(uint64_t block_height) {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{}", __func__);
// <= here because we might have crap in the db that we don't clear until we actually add the HF
// block later on. (This is a pretty slim edge case that happened on devnet and is probably
@ -289,7 +287,7 @@ namespace cryptonote {
uint64_t BlockchainSQLite::get_accrued_earnings(const std::string& address) {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{}", __func__);
auto earnings = prepared_maybe_get<int64_t>(
"SELECT amount FROM batched_payments_accrued WHERE address = ?",
@ -298,7 +296,7 @@ namespace cryptonote {
}
std::pair<std::vector<std::string>, std::vector<uint64_t>> BlockchainSQLite::get_all_accrued_earnings() {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{}", __func__);
std::pair<std::vector<std::string>, std::vector<uint64_t>> result;
auto& [addresses, amounts] = result;
@ -316,7 +314,7 @@ namespace cryptonote {
}
void BlockchainSQLite::calculate_rewards(hf hf_version, uint64_t distribution_amount, const service_nodes::service_node_info& sn_info, std::vector<cryptonote::batch_sn_payment>& payments) {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{}", __func__);
// Find out how much is due for the operator: fee_portions/PORTIONS * reward
assert(sn_info.portions_for_operator <= old::STAKING_PORTIONS);
@ -423,7 +421,7 @@ namespace cryptonote {
bool BlockchainSQLite::add_block(const cryptonote::block& block,
const service_nodes::service_node_list::state_t& service_nodes_state) {
auto block_height = get_block_height(block);
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__ << " called on height: " << block_height);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{} called on height: {}", __func__, block_height);
auto hf_version = block.major_version;
if (hf_version < hf::hf19_reward_batching) {
@ -433,13 +431,13 @@ namespace cryptonote {
auto fork_height = cryptonote::get_hard_fork_heights(m_nettype, hf::hf19_reward_batching);
if (block_height == fork_height.first.value_or(0)) {
MDEBUG("Batching of Service Node Rewards Begins");
oxen::log::debug(logcat, "Batching of Service Node Rewards Begins");
reset_database();
update_height(block_height - 1);
}
if (block_height != height + 1) {
MERROR(fmt::format("Block height ({}) out of sync with batching database ({})", block_height, height));
oxen::log::error(logcat, "Block height ({}) out of sync with batching database ({})", block_height, height);
return false;
}
@ -472,7 +470,7 @@ namespace cryptonote {
transaction.commit();
} catch (std::exception& e) {
MFATAL("Error adding reward payments: " << e.what());
oxen::log::error(logcat, "Error adding reward payments: {}", e.what());
return false;
}
return true;
@ -482,13 +480,13 @@ namespace cryptonote {
const service_nodes::service_node_list::state_t& service_nodes_state) {
auto block_height = get_block_height(block);
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__ << " called on height: " << block_height);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{} called on height: {}", __func__, block_height);
if (height < block_height) {
MDEBUG("Block above batching DB height skipping pop");
oxen::log::debug(logcat, "Block above batching DB height skipping pop");
return true;
}
if (block_height != height) {
MERROR("Block height out of sync with batching database");
oxen::log::error(logcat, "Block height out of sync with batching database");
return false;
}
@ -514,7 +512,7 @@ namespace cryptonote {
decrement_height();
transaction.commit();
} catch (std::exception& e) {
MFATAL("Error subtracting reward payments: " << e.what());
oxen::log::error(logcat, "Error subtracting reward payments: {}", e.what());
return false;
}
return true;
@ -524,10 +522,10 @@ namespace cryptonote {
const std::vector<std::tuple<crypto::public_key, uint64_t>>& miner_tx_vouts,
const std::vector<cryptonote::batch_sn_payment>& calculated_payments_from_batching_db,
uint64_t block_height) {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{}", __func__);
if (miner_tx_vouts.size() != calculated_payments_from_batching_db.size()) {
MERROR(fmt::format("Length of batch payments ({}) does not match block vouts ({})", calculated_payments_from_batching_db.size(), miner_tx_vouts.size()));
oxen::log::error(logcat, "Length of batch payments ({}) does not match block vouts ({})", calculated_payments_from_batching_db.size(), miner_tx_vouts.size());
return false;
}
@ -546,23 +544,23 @@ namespace cryptonote {
uint64_t amount = amt * BATCH_REWARD_FACTOR;
const auto& from_db = calculated_payments_from_batching_db[vout_index];
if (amount != from_db.amount) {
MERROR(fmt::format("Batched payout amount incorrect. Should be {}, not {}", from_db.amount, amount));
oxen::log::error(logcat, "Batched payout amount incorrect. Should be {}, not {}", from_db.amount, amount);
return false;
}
crypto::public_key out_eph_public_key{};
if (!cryptonote::get_deterministic_output_key(from_db.address_info.address, deterministic_keypair, vout_index, out_eph_public_key)) {
MERROR("Failed to generate output one-time public key");
oxen::log::error(logcat, "Failed to generate output one-time public key");
return false;
}
if (tools::view_guts(pubkey) != tools::view_guts(out_eph_public_key)) {
MERROR("Output ephemeral public key does not match");
oxen::log::error(logcat, "Output ephemeral public key does not match");
return false;
}
total_oxen_payout_in_vouts += amount;
finalised_payments.emplace_back(from_db.address_info, amount);
}
if (total_oxen_payout_in_vouts != total_oxen_payout_in_our_db) {
MERROR(fmt::format("Total batched payout amount incorrect. Should be {}, not {}", total_oxen_payout_in_our_db, total_oxen_payout_in_vouts));
oxen::log::error(logcat, "Total batched payout amount incorrect. Should be {}, not {}", total_oxen_payout_in_our_db, total_oxen_payout_in_vouts);
return false;
}
@ -570,7 +568,7 @@ namespace cryptonote {
}
bool BlockchainSQLite::save_payments(uint64_t block_height, const std::vector<batch_sn_payment>& paid_amounts) {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{}", __func__);
auto select_sum = prepared_st(
"SELECT amount from batched_payments_accrued WHERE address = ?");
@ -588,8 +586,7 @@ namespace cryptonote {
auto amount = static_cast<uint64_t>(*maybe_amount) / BATCH_REWARD_FACTOR * BATCH_REWARD_FACTOR;
if (amount != payment.amount) {
MERROR(fmt::format("Invalid amounts passed in to save payments for address {}: received {}, expected {} (truncated from {})",
address_str, payment.amount, amount, *maybe_amount));
oxen::log::error(logcat, "Invalid amounts passed in to save payments for address {}: received {}, expected {} (truncated from {})", address_str, payment.amount, amount, *maybe_amount);
return false;
}
@ -598,8 +595,7 @@ namespace cryptonote {
}
else {
// This shouldn't occur: we validate payout addresses much earlier in the block validation.
MERROR(fmt::format("Internal error: Invalid amounts passed in to save payments for address {}: that address has no accrued rewards",
address_str));
oxen::log::error(logcat, "Internal error: Invalid amounts passed in to save payments for address {}: that address has no accrued rewards", address_str);
return false;
}
@ -609,7 +605,7 @@ namespace cryptonote {
}
std::vector<cryptonote::batch_sn_payment> BlockchainSQLite::get_block_payments(uint64_t block_height) {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__ << " Called with height: " << block_height);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{} Called with height: {}", __func__, block_height);
std::vector<cryptonote::batch_sn_payment> payments_at_height;
auto paid = prepared_results<std::string_view, int64_t>(
@ -626,7 +622,7 @@ namespace cryptonote {
}
bool BlockchainSQLite::delete_block_payments(uint64_t block_height) {
LOG_PRINT_L3("BlockchainDB_SQLITE::" << __func__ << " Called with height: " << block_height);
oxen::log::trace(logcat, "BlockchainDB_SQLITE::{} Called with height: {}", __func__, block_height);
prepared_exec(
"DELETE FROM batched_payments_paid WHERE height_paid >= ?",
static_cast<int64_t>(block_height));

View File

@ -30,7 +30,6 @@
#include <string>
#include <filesystem>
#include "epee/misc_log_ex.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "cryptonote_core/cryptonote_tx_utils.h"
#include "sqlitedb/database.hpp"

View File

@ -35,6 +35,7 @@ target_link_libraries(blockchain_tools_common_libs INTERFACE
filesystem
Boost::program_options
SQLiteCpp
logging
extra)

View File

@ -34,6 +34,7 @@
#include <unordered_set>
#include <boost/archive/portable_binary_iarchive.hpp>
#include <boost/archive/portable_binary_oarchive.hpp>
#include <fstream>
#include "common/unordered_containers_boost_serialization.h"
#include "common/command_line.h"
#include "common/varint.h"
@ -46,9 +47,9 @@
#include "blockchain_db/blockchain_db.h"
#include "version.h"
#include "cryptonote_core/uptime_proof.h"
#include <fmt/std.h>
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
static auto logcat = oxen::log::Cat("bcutil");
namespace po = boost::program_options;
using namespace cryptonote;
@ -102,7 +103,7 @@ struct tx_data_t
vin.push_back(std::make_pair(txin->amount, cryptonote::relative_output_offsets_to_absolute(txin->key_offsets)));
else
{
LOG_PRINT_L0("Bad vin type in txid " << get_transaction_hash(tx));
oxen::log::warning(logcat, "Bad vin type in txid {}", get_transaction_hash(tx));
throw std::runtime_error("Bad vin type");
}
}
@ -116,7 +117,7 @@ struct tx_data_t
}
else
{
LOG_PRINT_L0("Bad vout type in txid " << get_transaction_hash(tx));
oxen::log::warning(logcat, "Bad vout type in txid {}", get_transaction_hash(tx));
throw std::runtime_error("Bad vout type");
}
}
@ -215,7 +216,7 @@ static std::unordered_set<ancestor> get_ancestry(const std::unordered_map<crypto
std::unordered_map<crypto::hash, std::unordered_set<ancestor>>::const_iterator i = ancestry.find(txid);
if (i == ancestry.end())
{
//MERROR("txid ancestry not found: " << txid);
//oxen::log::error(logcat, "txid ancestry not found: {}", txid);
//throw std::runtime_error("txid ancestry not found");
return std::unordered_set<ancestor>();
}
@ -234,7 +235,7 @@ static bool get_block_from_height(ancestry_state_t &state, BlockchainDB *db, uin
std::string bd = db->get_block_blob_from_height(height);
if (!cryptonote::parse_and_validate_block_from_blob(bd, b))
{
LOG_PRINT_L0("Bad block from db");
oxen::log::warning(logcat, "Bad block from db");
return false;
}
if (opt_cache_blocks)
@ -259,13 +260,13 @@ static bool get_transaction(ancestry_state_t &state, BlockchainDB *db, const cry
std::string bd;
if (!db->get_pruned_tx_blob(txid, bd))
{
LOG_PRINT_L0("Failed to get txid " << txid << " from db");
oxen::log::warning(logcat, "Failed to get txid {} from db", txid);
return false;
}
cryptonote::transaction tx;
if (!cryptonote::parse_and_validate_tx_base_from_blob(bd, tx))
{
LOG_PRINT_L0("Bad tx: " << txid);
oxen::log::warning(logcat, "Bad tx: {}", txid);
return false;
}
tx_data = ::tx_data_t(tx);
@ -304,7 +305,7 @@ static bool get_output_txid(ancestry_state_t &state, BlockchainDB *db, uint64_t
}
else
{
LOG_PRINT_L0("Bad vout type in txid " << cryptonote::get_transaction_hash(b.miner_tx));
oxen::log::warning(logcat, "Bad vout type in txid {}", cryptonote::get_transaction_hash(b.miner_tx));
return false;
}
}
@ -334,8 +335,6 @@ int main(int argc, char* argv[])
epee::string_tools::set_module_name_and_folder(argv[0]);
uint32_t log_level = 0;
tools::on_startup();
auto opt_size = command_line::boost_option_sizes();
@ -388,14 +387,17 @@ int main(int argc, char* argv[])
std::cout << desc_options << std::endl;
return 1;
}
mlog_configure(mlog_get_default_log_path("oxen-blockchain-ancestry.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else
mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str());
LOG_PRINT_L0("Starting...");
auto m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir);
auto log_file_path = m_config_folder + "oxen-blockchain-ancestry.log";
oxen::log::Level log_level;
if(auto level = oxen::logging::parse_level(command_line::get_arg(vm, arg_log_level).c_str())) {
log_level = *level;
} else {
std::cerr << "Incorrect log level: " << command_line::get_arg(vm, arg_log_level).c_str() << std::endl;
throw std::runtime_error{"Incorrect log level"};
}
oxen::logging::init(log_file_path, log_level);
oxen::log::warning(logcat, "Starting...");
std::string opt_data_dir = command_line::get_arg(vm, cryptonote::arg_data_dir);
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
@ -435,19 +437,19 @@ int main(int argc, char* argv[])
}
}
LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)");
oxen::log::warning(logcat, "Initializing source blockchain (BlockchainDB)");
blockchain_objects_t blockchain_objects = {};
Blockchain *core_storage = &blockchain_objects.m_blockchain;
BlockchainDB *db = new_db();
if (db == NULL)
{
LOG_ERROR("Failed to initialize a database");
oxen::log::error(logcat, "Failed to initialize a database");
throw std::runtime_error("Failed to initialize a database");
}
LOG_PRINT_L0("database: LMDB");
oxen::log::warning(logcat, "database: LMDB");
fs::path filename = fs::u8path(opt_data_dir) / db->get_db_name();
LOG_PRINT_L0("Loading blockchain from folder " << filename << " ...");
oxen::log::warning(logcat, "Loading blockchain from folder {} ...", filename);
try
{
@ -455,20 +457,20 @@ int main(int argc, char* argv[])
}
catch (const std::exception& e)
{
LOG_PRINT_L0("Error opening database: " << e.what());
oxen::log::warning(logcat, "Error opening database: {}", e.what());
return 1;
}
r = core_storage->init(db, nullptr /*ons_db*/, nullptr, net_type);
CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage");
LOG_PRINT_L0("Source blockchain storage initialized OK");
oxen::log::warning(logcat, "Source blockchain storage initialized OK");
std::vector<crypto::hash> start_txids;
ancestry_state_t state;
fs::path state_file_path = fs::u8path(opt_data_dir) / "ancestry-state.bin";
LOG_PRINT_L0("Loading state data from " << state_file_path);
oxen::log::warning(logcat, "Loading state data from {}", state_file_path);
fs::ifstream state_data_in;
state_data_in.open(state_file_path, std::ios_base::binary | std::ios_base::in);
if (!state_data_in.fail())
@ -480,7 +482,7 @@ int main(int argc, char* argv[])
}
catch (const std::exception &e)
{
MERROR("Failed to load state data from " << state_file_path << ", restarting from scratch");
oxen::log::error(logcat, "Failed to load state data from {}, restarting from scratch", state_file_path);
state = ancestry_state_t();
}
state_data_in.close();
@ -494,7 +496,7 @@ int main(int argc, char* argv[])
const uint64_t db_height = db->height();
if (opt_refresh)
{
MINFO("Starting from height " << state.height);
oxen::log::info(logcat, "Starting from height {}", state.height);
state.block_cache.reserve(db_height);
for (uint64_t h = state.height; h < db_height; ++h)
{
@ -504,7 +506,7 @@ int main(int argc, char* argv[])
cryptonote::block b;
if (!cryptonote::parse_and_validate_block_from_blob(bd, b))
{
LOG_PRINT_L0("Bad block from db");
oxen::log::warning(logcat, "Bad block from db");
return 1;
}
if (opt_cache_blocks)
@ -535,13 +537,13 @@ int main(int argc, char* argv[])
std::string bd;
if (!db->get_pruned_tx_blob(txid, bd))
{
LOG_PRINT_L0("Failed to get txid " << txid << " from db");
oxen::log::warning(logcat, "Failed to get txid {} from db", txid);
return 1;
}
cryptonote::transaction tx;
if (!cryptonote::parse_and_validate_tx_base_from_blob(bd, tx))
{
LOG_PRINT_L0("Bad tx: " << txid);
oxen::log::warning(logcat, "Bad tx: {}", txid);
return 1;
}
tx_data = ::tx_data_t(tx);
@ -566,7 +568,7 @@ int main(int argc, char* argv[])
crypto::hash output_txid;
if (!get_output_txid(state, db, amount, offset, output_txid))
{
LOG_PRINT_L0("Output originating transaction not found");
oxen::log::warning(logcat, "Output originating transaction not found");
return 1;
}
add_ancestry(state.ancestry, txid, get_ancestry(state.ancestry, output_txid));
@ -575,19 +577,19 @@ int main(int argc, char* argv[])
}
const size_t ancestry_size = get_ancestry(state.ancestry, txid).size();
block_ancestry_size += ancestry_size;
MINFO(txid << ": " << ancestry_size);
oxen::log::info(logcat, "{}: {}", txid, ancestry_size);
}
if (!txids.empty())
{
std::string stats_msg;
MINFO("Height " << h << ": " << (block_ancestry_size / txids.size()) << " average over " << txids.size() << stats_msg);
oxen::log::info(logcat, "Height {}: {} average over {}{}", h, (block_ancestry_size / txids.size()), txids.size(), stats_msg);
}
state.height = h;
if (stop_requested)
break;
}
LOG_PRINT_L0("Saving state data to " << state_file_path);
oxen::log::warning(logcat, "Saving state data to {}", state_file_path);
std::ofstream state_data_out;
state_data_out.open(state_file_path, std::ios_base::binary | std::ios_base::out | std::ios::trunc);
if (!state_data_out.fail())
@ -599,7 +601,7 @@ int main(int argc, char* argv[])
}
catch (const std::exception &e)
{
MERROR("Failed to save state data to " << state_file_path);
oxen::log::error(logcat, "Failed to save state data to {}", state_file_path);
}
state_data_out.close();
}
@ -608,8 +610,8 @@ int main(int argc, char* argv[])
{
if (state.height < db_height)
{
MWARNING("The state file is only built up to height " << state.height << ", but the blockchain reached height " << db_height);
MWARNING("You may want to run with --refresh if you want to get ancestry for newer data");
oxen::log::warning(logcat, "The state file is only built up to height {}, but the blockchain reached height {}", state.height, db_height);
oxen::log::warning(logcat, "You may want to run with --refresh if you want to get ancestry for newer data");
}
}
@ -622,7 +624,7 @@ int main(int argc, char* argv[])
crypto::hash txid;
if (!get_output_txid(state, db, output_amount, output_offset, txid))
{
LOG_PRINT_L0("Output not found in db");
oxen::log::warning(logcat, "Output not found in db");
return 1;
}
start_txids.push_back(txid);
@ -633,7 +635,7 @@ int main(int argc, char* argv[])
cryptonote::block b;
if (!cryptonote::parse_and_validate_block_from_blob(bd, b))
{
LOG_PRINT_L0("Bad block from db");
oxen::log::warning(logcat, "Bad block from db");
return 1;
}
for (const crypto::hash &txid: b.tx_hashes)
@ -642,13 +644,13 @@ int main(int argc, char* argv[])
if (start_txids.empty())
{
LOG_PRINT_L0("No transaction(s) to check");
oxen::log::warning(logcat, "No transaction(s) to check");
return 1;
}
for (const crypto::hash &start_txid: start_txids)
{
LOG_PRINT_L0("Checking ancestry for txid " << start_txid);
oxen::log::warning(logcat, "Checking ancestry for txid {}", start_txid);
std::unordered_map<ancestor, unsigned int> ancestry;
@ -684,22 +686,22 @@ int main(int argc, char* argv[])
crypto::hash output_txid;
if (!get_output_txid(state, db, amount, offset, output_txid))
{
LOG_PRINT_L0("Output originating transaction not found");
oxen::log::warning(logcat, "Output originating transaction not found");
return 1;
}
add_ancestry(state.ancestry, txid, get_ancestry(state.ancestry, output_txid));
txids.push_back(output_txid);
MDEBUG("adding txid: " << output_txid);
oxen::log::debug(logcat, "adding txid: {}", output_txid);
}
}
}
}
MINFO("Ancestry for " << start_txid << ": " << get_deduplicated_ancestry(ancestry) << " / " << get_full_ancestry(ancestry));
oxen::log::info(logcat, "Ancestry for {}: {} / {}", start_txid, get_deduplicated_ancestry(ancestry), get_full_ancestry(ancestry));
for (const auto &i: ancestry)
{
MINFO(cryptonote::print_money(i.first.amount) << "/" << i.first.offset << ": " << i.second);
oxen::log::info(logcat, "{}/{}: {}", cryptonote::print_money(i.first.amount), i.first.offset, i.second);
}
}
@ -707,10 +709,7 @@ done:
core_storage->deinit();
if (opt_show_cache_stats)
MINFO("cache: txes " << std::to_string(cached_txes*100./total_txes)
<< "%, blocks " << std::to_string(cached_blocks*100./total_blocks)
<< "%, outputs " << std::to_string(cached_outputs*100./total_outputs)
<< "%");
oxen::log::info(logcat, "cache: txes {}%, blocks {}%, outputs {}%", std::to_string(cached_txes*100./total_txes), std::to_string(cached_blocks*100./total_blocks), std::to_string(cached_outputs*100./total_outputs));
return 0;

View File

@ -46,9 +46,9 @@
#include "wallet/ringdb.h"
#include "version.h"
#include "cryptonote_core/uptime_proof.h"
#include <fmt/std.h>
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
static auto logcat = oxen::log::Cat("bcutil");
namespace po = boost::program_options;
using namespace cryptonote;
@ -90,7 +90,7 @@ static bool parse_db_sync_mode(std::string db_sync_mode)
auto options = tools::split_any(db_sync_mode, " :", true);
for(const auto &option : options)
MDEBUG("option: " << option);
oxen::log::debug(logcat, "option: {}", option);
// default to fast:async:1
uint64_t DEFAULT_FLAGS = DBF_FAST;
@ -206,14 +206,14 @@ static int resize_env(const char *db_path)
auto si = fs::space(fs::u8path(db_path));
if(si.available < needed)
{
MERROR("!! WARNING: Insufficient free space to extend database !!: " << (si.available / 1000000) << " MB available");
oxen::log::error(logcat, "!! WARNING: Insufficient free space to extend database !!: {} MB available", (si.available / 1000000));
return ENOSPC;
}
}
catch(...)
{
// print something but proceed.
MWARNING("Unable to query free disk space.");
oxen::log::warning(logcat, "Unable to query free disk space.");
}
mapsize += needed;
@ -227,11 +227,11 @@ static void init(fs::path cache_filename)
bool tx_active = false;
int dbr;
MINFO("Creating spent output cache in " << cache_filename);
oxen::log::info(logcat, "Creating spent output cache in {}", cache_filename);
std::error_code ec;
if (fs::create_directories(cache_filename, ec); ec)
MWARNING("Failed to create output cache directory " << cache_filename << ": " << ec.message());
oxen::log::warning(logcat, "Failed to create output cache directory {}: {}", cache_filename, ec.message());
int flags = 0;
if (db_flags & DBF_FAST)
@ -392,7 +392,7 @@ static bool for_all_transactions(const fs::path& filename, uint64_t& start_idx,
std::string_view bd{static_cast<const char*>(v.mv_data), v.mv_size};
serialization::parse_binary(bd, tx);
} catch (const std::exception& e) {
LOG_ERROR("Failed to parse transaction from blob: " << e.what());
oxen::log::error(logcat, "Failed to parse transaction from blob: {}", e.what());
return false;
}
@ -607,7 +607,7 @@ static std::vector<uint64_t> canonicalize(const std::vector<uint64_t> &v)
}
if (c.size() < v.size())
{
MINFO("Ring has duplicate member(s): " << tools::join(" ", v));
oxen::log::info(logcat, "Ring has duplicate member(s): {}", tools::join(" ", v));
}
return c;
}
@ -955,7 +955,7 @@ static void open_db(const fs::path& filename, MDB_env** env, MDB_txn** txn, MDB_
{
std::error_code ec;
if (fs::create_directories(filename, ec); ec)
MWARNING("Failed to create lmdb path " << filename << ": " << ec.message());
oxen::log::warning(logcat, "Failed to create lmdb path {}: {}", filename, ec.message());
int flags = MDB_RDONLY;
if (db_flags & DBF_FAST)
@ -967,7 +967,7 @@ static void open_db(const fs::path& filename, MDB_env** env, MDB_txn** txn, MDB_
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to create LDMB environment: " + std::string(mdb_strerror(dbr)));
dbr = mdb_env_set_maxdbs(*env, 1);
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to set max env dbs: " + std::string(mdb_strerror(dbr)));
MINFO("Opening oxen blockchain at " << filename);
oxen::log::info(logcat, "Opening oxen blockchain at {}", filename);
dbr = mdb_env_open(*env, filename.string().c_str(), flags, 0664);
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to open rings database file '"
+ filename.u8string() + "': " + std::string(mdb_strerror(dbr)));
@ -1065,7 +1065,7 @@ static std::vector<std::pair<uint64_t, uint64_t>> load_outputs(const fs::path& f
if (!f)
{
MERROR("Failed to load outputs from " << filename << ": " << strerror(errno));
oxen::log::error(logcat, "Failed to load outputs from {}: {}", filename, strerror(errno));
return {};
}
while (1)
@ -1073,7 +1073,7 @@ static std::vector<std::pair<uint64_t, uint64_t>> load_outputs(const fs::path& f
char s[256];
if (!fgets(s, sizeof(s), f))
{
MERROR("Error reading from " << filename << ": " << strerror(errno));
oxen::log::error(logcat, "Error reading from {}: {}", filename, strerror(errno));
break;
}
if (feof(f))
@ -1091,7 +1091,7 @@ static std::vector<std::pair<uint64_t, uint64_t>> load_outputs(const fs::path& f
}
if (amount == std::numeric_limits<uint64_t>::max())
{
MERROR("Bad format in " << filename);
oxen::log::error(logcat, "Bad format in {}", filename);
continue;
}
if (sscanf(s, "%" PRIu64 "*%" PRIu64, &offset, &num_offsets) == 2 && num_offsets < std::numeric_limits<uint64_t>::max() - offset)
@ -1105,7 +1105,7 @@ static std::vector<std::pair<uint64_t, uint64_t>> load_outputs(const fs::path& f
}
else
{
MERROR("Bad format in " << filename);
oxen::log::error(logcat, "Bad format in {}", filename);
continue;
}
}
@ -1124,7 +1124,7 @@ static bool export_spent_outputs(MDB_cursor* cur, const fs::path& filename)
if (!f)
{
MERROR("Failed to open " << filename << ": " << strerror(errno));
oxen::log::error(logcat, "Failed to open {}: {}", filename, strerror(errno));
return false;
}
@ -1141,7 +1141,7 @@ static bool export_spent_outputs(MDB_cursor* cur, const fs::path& filename)
if (dbr)
{
fclose(f);
MERROR("Failed to enumerate spent outputs: " << mdb_strerror(dbr));
oxen::log::error(logcat, "Failed to enumerate spent outputs: {}", mdb_strerror(dbr));
return false;
}
const uint64_t amount = *(const uint64_t*)k.mv_data;
@ -1178,9 +1178,6 @@ int main(int argc, char* argv[])
TRY_ENTRY();
epee::string_tools::set_module_name_and_folder(argv[0]);
uint32_t log_level = 0;
tools::on_startup();
auto opt_size = command_line::boost_option_sizes();
@ -1243,13 +1240,17 @@ int main(int argc, char* argv[])
return 1;
}
mlog_configure(mlog_get_default_log_path("oxen-blockchain-mark-spent-outputs.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else
mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str());
LOG_PRINT_L0("Starting...");
auto m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir);
auto log_file_path = m_config_folder + "oxen-blockchain-mark-spent-outputs.log";
oxen::log::Level log_level;
if(auto level = oxen::logging::parse_level(command_line::get_arg(vm, arg_log_level).c_str())) {
log_level = *level;
} else {
std::cerr << "Incorrect log level: " << command_line::get_arg(vm, arg_log_level).c_str() << std::endl;
throw std::runtime_error{"Incorrect log level"};
}
oxen::logging::init(log_file_path, log_level);
oxen::log::warning(logcat, "Starting...");
fs::path output_file_path = fs::u8path(command_line::get_arg(vm, arg_blackball_db_dir));
bool opt_rct_only = command_line::get_arg(vm, arg_rct_only);
@ -1265,7 +1266,7 @@ int main(int argc, char* argv[])
std::string db_sync_mode = command_line::get_arg(vm, arg_db_sync_mode);
if (!parse_db_sync_mode(db_sync_mode))
{
MERROR("Invalid db sync mode: " << db_sync_mode);
oxen::log::error(logcat, "Invalid db sync mode: {}", db_sync_mode);
return 1;
}
@ -1274,7 +1275,7 @@ int main(int argc, char* argv[])
inputs.push_back(fs::u8path(in));
if (inputs.empty())
{
LOG_PRINT_L0("No inputs given");
oxen::log::warning(logcat, "No inputs given");
return 1;
}
@ -1288,7 +1289,7 @@ int main(int argc, char* argv[])
fs::path cache_dir = output_file_path / "spent-outputs-cache";
init(cache_dir);
LOG_PRINT_L0("Scanning for spent outputs...");
oxen::log::warning(logcat, "Scanning for spent outputs...");
size_t done = 0;
@ -1317,7 +1318,7 @@ int main(int argc, char* argv[])
{
if (!start_blackballed_outputs)
{
MINFO("Spent outputs database is empty. Either you haven't run the analysis mode yet, or there is really no output marked as spent.");
oxen::log::info(logcat, "Spent outputs database is empty. Either you haven't run the analysis mode yet, or there is really no output marked as spent.");
goto skip_secondary_passes;
}
MDB_txn *txn;
@ -1342,7 +1343,7 @@ int main(int argc, char* argv[])
{
uint64_t window_front = (height / STAT_WINDOW - 1) * STAT_WINDOW;
uint64_t window_back = window_front + STAT_WINDOW - 1;
LOG_PRINT_L0(window_front << "-" << window_back << ": " << (100.0f * outs_spent / outs_total) << "% ( " << outs_spent << " / " << outs_total << " )");
oxen::log::warning(logcat, "{}-{}: {}% ( {} / {} )", window_front, window_back, (100.0f * outs_spent / outs_total), outs_spent, outs_total);
outs_total = outs_spent = 0;
}
}
@ -1359,11 +1360,11 @@ int main(int argc, char* argv[])
{
uint64_t window_front = (height / STAT_WINDOW) * STAT_WINDOW;
uint64_t window_back = height;
LOG_PRINT_L0(window_front << "-" << window_back << ": " << (100.0f * outs_spent / outs_total) << "% ( " << outs_spent << " / " << outs_total << " )");
oxen::log::warning(logcat, "{}-{}: {}% ( {} / {} )", window_front, window_back, (100.0f * outs_spent / outs_total), outs_spent, outs_total);
}
if (stop_requested)
{
MINFO("Stopping scan...");
oxen::log::info(logcat, "Stopping scan...");
return false;
}
return true;
@ -1376,7 +1377,7 @@ int main(int argc, char* argv[])
if (!extra_spent_outputs.empty())
{
MINFO("Adding " << extra_spent_outputs.size() << " extra spent outputs");
oxen::log::info(logcat, "Adding {} extra spent outputs", extra_spent_outputs.size());
MDB_txn *txn;
int dbr = mdb_txn_begin(env, NULL, 0, &txn);
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to create LMDB transaction: " + std::string(mdb_strerror(dbr)));
@ -1411,9 +1412,9 @@ int main(int argc, char* argv[])
if (n > 0 && start_idx == 0)
{
start_idx = find_first_diverging_transaction(inputs[0], inputs[n]);
LOG_PRINT_L0("First diverging transaction at " << start_idx);
oxen::log::warning(logcat, "First diverging transaction at {}", start_idx);
}
LOG_PRINT_L0("Reading blockchain from " << inputs[n] << " from " << start_idx);
oxen::log::warning(logcat, "Reading blockchain from {} from {}", inputs[n], start_idx);
MDB_txn *txn;
int dbr = mdb_txn_begin(env, NULL, 0, &txn);
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to create LMDB transaction: " + std::string(mdb_strerror(dbr)));
@ -1450,7 +1451,7 @@ int main(int argc, char* argv[])
const std::pair<uint64_t, uint64_t> output = std::make_pair(txin.amount, absolute[0]);
if (opt_verbose)
{
MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in a 1-ring");
oxen::log::info(logcat, "Marking output {}/{} as spent, due to being used in a 1-ring", output.first, output.second);
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
}
blackballs.push_back(output);
@ -1464,7 +1465,7 @@ int main(int argc, char* argv[])
const std::pair<uint64_t, uint64_t> output = std::make_pair(txin.amount, absolute[o]);
if (opt_verbose)
{
MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in " << new_ring.size() << " identical " << new_ring.size() << "-rings");
oxen::log::info(logcat, "Marking output {}/{} as spent, due to being used in {} identical {}-rings", output.first, output.second, new_ring.size(), new_ring.size());
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
}
blackballs.push_back(output);
@ -1479,7 +1480,7 @@ int main(int argc, char* argv[])
const std::pair<uint64_t, uint64_t> output = std::make_pair(txin.amount, o);
if (opt_verbose)
{
MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to as many outputs of that amount being spent as exist so far");
oxen::log::info(logcat, "Marking output {}/{} as spent, due to as many outputs of that amount being spent as exist so far", output.first, output.second);
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
}
blackballs.push_back(output);
@ -1494,7 +1495,7 @@ int main(int argc, char* argv[])
const std::pair<uint64_t, uint64_t> output = std::make_pair(txin.amount, absolute[o]);
if (opt_verbose)
{
MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in " << new_ring.size() << " subsets of " << new_ring.size() << "-rings");
oxen::log::info(logcat, "Marking output {}/{} as spent, due to being used in {} subsets of {}-rings", output.first, output.second, new_ring.size(), new_ring.size());
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
}
blackballs.push_back(output);
@ -1504,12 +1505,11 @@ int main(int argc, char* argv[])
}
else if (n > 0 && get_relative_ring(txn, txin.k_image, relative_ring))
{
MDEBUG("Key image " << txin.k_image << " already seen: "
"rings " << tools::join(" ", relative_ring) << ", " << tools::join(" ", txin.key_offsets));
oxen::log::debug(logcat, "Key image {} already seen: rings {}, {}", txin.k_image, tools::join(" ", relative_ring), tools::join(" ", txin.key_offsets));
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
if (relative_ring != txin.key_offsets)
{
MDEBUG("Rings are different");
oxen::log::debug(logcat, "Rings are different");
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
const std::vector<uint64_t> r0 = cryptonote::relative_output_offsets_to_absolute(relative_ring);
const std::vector<uint64_t> r1 = cryptonote::relative_output_offsets_to_absolute(txin.key_offsets);
@ -1521,7 +1521,7 @@ int main(int argc, char* argv[])
}
if (common.empty())
{
MERROR("Rings for the same key image are disjoint");
oxen::log::error(logcat, "Rings for the same key image are disjoint");
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
}
else if (common.size() == 1)
@ -1529,7 +1529,7 @@ int main(int argc, char* argv[])
const std::pair<uint64_t, uint64_t> output = std::make_pair(txin.amount, common[0]);
if (opt_verbose)
{
MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in rings with a single common element");
oxen::log::info(logcat, "Marking output {}/{} as spent, due to being used in rings with a single common element", output.first, output.second);
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
}
blackballs.push_back(output);
@ -1538,7 +1538,7 @@ int main(int argc, char* argv[])
}
else
{
MDEBUG("The intersection has more than one element, it's still ok");
oxen::log::debug(logcat, "The intersection has more than one element, it's still ok");
std::cout << "\r" << start_idx << "/" << n_txes << " \r" << std::flush;
for (const auto &out: r0)
if (std::find(common.begin(), common.end(), out) != common.end())
@ -1594,7 +1594,7 @@ int main(int argc, char* argv[])
if (stop_requested)
{
MINFO("Stopping scan...");
oxen::log::info(logcat, "Stopping scan...");
return false;
}
return true;
@ -1602,7 +1602,7 @@ int main(int argc, char* argv[])
mdb_cursor_close(cur);
dbr = mdb_txn_commit(txn);
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to commit txn creating/opening database: " + std::string(mdb_strerror(dbr)));
LOG_PRINT_L0("blockchain from " << inputs[n] << " processed till tx idx " << start_idx);
oxen::log::warning(logcat, "blockchain from {} processed till tx idx {}", inputs[n], start_idx);
if (stop_requested)
break;
}
@ -1621,7 +1621,7 @@ int main(int argc, char* argv[])
while (!work_spent.empty())
{
LOG_PRINT_L0("Secondary pass on " << work_spent.size() << " spent outputs");
oxen::log::warning(logcat, "Secondary pass on {} spent outputs", work_spent.size());
int dbr = resize_env(cache_dir.string().c_str());
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to resize LMDB database: " + std::string(mdb_strerror(dbr)));
@ -1659,8 +1659,7 @@ int main(int argc, char* argv[])
const std::pair<uint64_t, uint64_t> output = std::make_pair(od.amount, last_unknown);
if (opt_verbose)
{
MINFO("Marking output " << output.first << "/" << output.second << " as spent, due to being used in a " <<
absolute.size() << "-ring where all other outputs are known to be spent");
oxen::log::info(logcat, "Marking output {}/{} as spent, due to being used in a {}-ring where all other outputs are known to be spent", output.first, output.second, absolute.size());
}
blackballs.push_back(output);
if (add_spent_output(cur, output_data(od.amount, last_unknown)))
@ -1671,7 +1670,7 @@ int main(int argc, char* argv[])
if (stop_requested)
{
MINFO("Stopping secondary passes. Secondary passes are not incremental, they will re-run fully.");
oxen::log::info(logcat, "Stopping secondary passes. Secondary passes are not incremental, they will re-run fully.");
return 0;
}
}
@ -1687,15 +1686,15 @@ int main(int argc, char* argv[])
skip_secondary_passes:
uint64_t diff = get_num_spent_outputs() - start_blackballed_outputs;
LOG_PRINT_L0(std::to_string(diff) << " new outputs marked as spent, " << get_num_spent_outputs() << " total outputs marked as spent");
oxen::log::warning(logcat, "{} new outputs marked as spent, {} total outputs marked as spent", std::to_string(diff), get_num_spent_outputs());
MDB_txn *txn;
dbr = mdb_txn_begin(env, NULL, MDB_RDONLY, &txn);
CHECK_AND_ASSERT_THROW_MES(!dbr, "Failed to create LMDB transaction: " + std::string(mdb_strerror(dbr)));
uint64_t pre_rct = 0, rct = 0;
get_num_outputs(txn0, cur0, dbi0, pre_rct, rct);
MINFO("Total pre-rct outputs: " << pre_rct);
MINFO("Total rct outputs: " << rct);
oxen::log::info(logcat, "Total pre-rct outputs: {}", pre_rct);
oxen::log::info(logcat, "Total rct outputs: {}", rct);
static const struct { const char *key; uint64_t base; } stat_keys[] = {
{ "pre-rct-ring-size-1", pre_rct }, { "rct-ring-size-1", rct },
{ "pre-rct-duplicate-rings", pre_rct }, { "rct-duplicate-rings", rct },
@ -1711,7 +1710,7 @@ skip_secondary_passes:
if (!get_stat(txn, key.key, data))
data = 0;
float percent = key.base ? 100.0f * data / key.base : 0.0f;
MINFO(key.key << ": " << data << " (" << percent << "%)");
oxen::log::info(logcat, "{}: {} ({}%)", key.key, data, percent);
}
mdb_txn_abort(txn);
@ -1728,7 +1727,7 @@ skip_secondary_passes:
mdb_txn_abort(txn);
}
LOG_PRINT_L0("Blockchain spent output data exported OK");
oxen::log::warning(logcat, "Blockchain spent output data exported OK");
close_db(env0, txn0, cur0, dbi0);
close();
return 0;

View File

@ -34,9 +34,9 @@
#include "blockchain_db/blockchain_db.h"
#include "cryptonote_core/uptime_proof.h"
#include "version.h"
#include <fmt/std.h>
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
static auto logcat = oxen::log::Cat("bcutil");
namespace po = boost::program_options;
using namespace cryptonote;
@ -46,9 +46,6 @@ int main(int argc, char* argv[])
TRY_ENTRY();
epee::string_tools::set_module_name_and_folder(argv[0]);
uint32_t log_level = 0;
tools::on_startup();
auto opt_size = command_line::boost_option_sizes();
@ -90,13 +87,17 @@ int main(int argc, char* argv[])
return 1;
}
mlog_configure(mlog_get_default_log_path("oxen-blockchain-depth.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else
mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str());
LOG_PRINT_L0("Starting...");
auto m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir);
auto log_file_path = m_config_folder + "oxen-blockchain-depth.log";
oxen::log::Level log_level;
if(auto level = oxen::logging::parse_level(command_line::get_arg(vm, arg_log_level).c_str())) {
log_level = *level;
} else {
std::cerr << "Incorrect log level: " << command_line::get_arg(vm, arg_log_level).c_str() << std::endl;
throw std::runtime_error{"Incorrect log level"};
}
oxen::logging::init(log_file_path, log_level);
oxen::log::warning(logcat, "Starting...");
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
bool opt_devnet = command_line::get_arg(vm, cryptonote::arg_devnet_on);
@ -120,19 +121,19 @@ int main(int argc, char* argv[])
}
}
LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)");
oxen::log::warning(logcat, "Initializing source blockchain (BlockchainDB)");
blockchain_objects_t blockchain_objects = {};
Blockchain *core_storage = &blockchain_objects.m_blockchain;
BlockchainDB *db = new_db();
if (db == NULL)
{
LOG_ERROR("Failed to initialize a database");
oxen::log::error(logcat, "Failed to initialize a database");
throw std::runtime_error("Failed to initialize a database");
}
LOG_PRINT_L0("database: LMDB");
oxen::log::warning(logcat, "database: LMDB");
const fs::path filename = fs::u8path(command_line::get_arg(vm, cryptonote::arg_data_dir)) / db->get_db_name();
LOG_PRINT_L0("Loading blockchain from folder " << filename << " ...");
oxen::log::warning(logcat, "Loading blockchain from folder {} ...", filename);
try
{
@ -140,13 +141,13 @@ int main(int argc, char* argv[])
}
catch (const std::exception& e)
{
LOG_PRINT_L0("Error opening database: " << e.what());
oxen::log::warning(logcat, "Error opening database: {}", e.what());
return 1;
}
r = core_storage->init(db, nullptr /*ons_db*/, nullptr, net_type);
CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage");
LOG_PRINT_L0("Source blockchain storage initialized OK");
oxen::log::warning(logcat, "Source blockchain storage initialized OK");
std::vector<crypto::hash> start_txids;
if (!opt_txid_string.empty())
@ -159,7 +160,7 @@ int main(int argc, char* argv[])
cryptonote::block b;
if (!cryptonote::parse_and_validate_block_from_blob(bd, b))
{
LOG_PRINT_L0("Bad block from db");
oxen::log::warning(logcat, "Bad block from db");
return 1;
}
for (const crypto::hash &txid: b.tx_hashes)
@ -170,7 +171,7 @@ int main(int argc, char* argv[])
if (start_txids.empty())
{
LOG_PRINT_L0("No transaction(s) to check");
oxen::log::warning(logcat, "No transaction(s) to check");
return 1;
}
@ -180,31 +181,31 @@ int main(int argc, char* argv[])
uint64_t depth = 0;
bool coinbase = false;
LOG_PRINT_L0("Checking depth for txid " << start_txid);
oxen::log::warning(logcat, "Checking depth for txid {}", start_txid);
std::vector<crypto::hash> txids(1, start_txid);
while (!coinbase)
{
LOG_PRINT_L0("Considering "<< txids.size() << " transaction(s) at depth " << depth);
oxen::log::warning(logcat, "Considering {} transaction(s) at depth {}", txids.size(), depth);
std::vector<crypto::hash> new_txids;
for (const crypto::hash &txid: txids)
{
std::string bd;
if (!db->get_pruned_tx_blob(txid, bd))
{
LOG_PRINT_L0("Failed to get txid " << txid << " from db");
oxen::log::warning(logcat, "Failed to get txid {} from db", txid);
return 1;
}
cryptonote::transaction tx;
if (!cryptonote::parse_and_validate_tx_base_from_blob(bd, tx))
{
LOG_PRINT_L0("Bad tx: " << txid);
oxen::log::warning(logcat, "Bad tx: {}", txid);
return 1;
}
for (size_t ring = 0; ring < tx.vin.size(); ++ring)
{
if (std::holds_alternative<cryptonote::txin_gen>(tx.vin[ring]))
{
MDEBUG(txid << " is a coinbase transaction");
oxen::log::debug(logcat, "{} is a coinbase transaction", txid);
coinbase = true;
goto done;
}
@ -220,7 +221,7 @@ int main(int argc, char* argv[])
cryptonote::block b;
if (!cryptonote::parse_and_validate_block_from_blob(bd, b))
{
LOG_PRINT_L0("Bad block from db");
oxen::log::warning(logcat, "Bad block from db");
return 1;
}
// find the tx which created this output
@ -233,13 +234,13 @@ int main(int argc, char* argv[])
{
found = true;
new_txids.push_back(cryptonote::get_transaction_hash(b.miner_tx));
MDEBUG("adding txid: " << cryptonote::get_transaction_hash(b.miner_tx));
oxen::log::debug(logcat, "adding txid: {}", cryptonote::get_transaction_hash(b.miner_tx));
break;
}
}
else
{
LOG_PRINT_L0("Bad vout type in txid " << cryptonote::get_transaction_hash(b.miner_tx));
oxen::log::warning(logcat, "Bad vout type in txid {}", cryptonote::get_transaction_hash(b.miner_tx));
return 1;
}
}
@ -249,13 +250,13 @@ int main(int argc, char* argv[])
break;
if (!db->get_pruned_tx_blob(block_txid, bd))
{
LOG_PRINT_L0("Failed to get txid " << block_txid << " from db");
oxen::log::warning(logcat, "Failed to get txid {} from db", block_txid);
return 1;
}
cryptonote::transaction tx2;
if (!cryptonote::parse_and_validate_tx_base_from_blob(bd, tx2))
{
LOG_PRINT_L0("Bad tx: " << block_txid);
oxen::log::warning(logcat, "Bad tx: {}", block_txid);
return 1;
}
for (size_t out = 0; out < tx2.vout.size(); ++out)
@ -266,27 +267,27 @@ int main(int argc, char* argv[])
{
found = true;
new_txids.push_back(block_txid);
MDEBUG("adding txid: " << block_txid);
oxen::log::debug(logcat, "adding txid: {}", block_txid);
break;
}
}
else
{
LOG_PRINT_L0("Bad vout type in txid " << block_txid);
oxen::log::warning(logcat, "Bad vout type in txid {}", block_txid);
return 1;
}
}
}
if (!found)
{
LOG_PRINT_L0("Output originating transaction not found");
oxen::log::warning(logcat, "Output originating transaction not found");
return 1;
}
}
}
else
{
LOG_PRINT_L0("Bad vin type in txid " << txid);
oxen::log::warning(logcat, "Bad vin type in txid {}", txid);
return 1;
}
}
@ -298,15 +299,15 @@ int main(int argc, char* argv[])
}
}
done:
LOG_PRINT_L0("Min depth for txid " << start_txid << ": " << depth);
oxen::log::warning(logcat, "Min depth for txid {}: {}", start_txid, depth);
depths.push_back(depth);
}
uint64_t cumulative_depth = 0;
for (uint64_t depth: depths)
cumulative_depth += depth;
LOG_PRINT_L0("Average min depth for " << start_txids.size() << " transaction(s): " << cumulative_depth/(float)depths.size());
LOG_PRINT_L0("Median min depth for " << start_txids.size() << " transaction(s): " << tools::median(std::move(depths)));
oxen::log::warning(logcat, "Average min depth for {} transaction(s): {}", start_txids.size(), cumulative_depth/(float)depths.size());
oxen::log::warning(logcat, "Median min depth for {} transaction(s): {}", start_txids.size(), tools::median(std::move(depths)));
core_storage->deinit();
return 0;

View File

@ -34,9 +34,9 @@
#include "blockchain_objects.h"
#include "version.h"
#include "cryptonote_core/uptime_proof.h"
#include <fmt/std.h>
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
static auto logcat = oxen::log::Cat("bcutil");
namespace po = boost::program_options;
@ -45,13 +45,9 @@ int main(int argc, char* argv[])
TRY_ENTRY();
epee::string_tools::set_module_name_and_folder(argv[0]);
uint32_t log_level = 0;
uint64_t block_stop = 0;
bool blocks_dat = false;
tools::on_startup();
auto opt_size = command_line::boost_option_sizes();
po::options_description desc_cmd_only("Command line options", opt_size.first, opt_size.second);
@ -92,14 +88,19 @@ int main(int argc, char* argv[])
return 1;
}
mlog_configure(mlog_get_default_log_path("oxen-blockchain-export.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else
mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str());
block_stop = command_line::get_arg(vm, arg_block_stop);
LOG_PRINT_L0("Starting...");
auto m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir);
auto log_file_path = m_config_folder + "oxen-blockchain-export.log";
oxen::log::Level log_level;
if(auto level = oxen::logging::parse_level(command_line::get_arg(vm, arg_log_level).c_str())) {
log_level = *level;
} else {
std::cerr << "Incorrect log level: " << command_line::get_arg(vm, arg_log_level).c_str() << std::endl;
throw std::runtime_error{"Incorrect log level"};
}
oxen::logging::init(log_file_path, log_level);
oxen::log::warning(logcat, "Starting...");
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
bool opt_devnet = command_line::get_arg(vm, cryptonote::arg_devnet_on);
@ -117,42 +118,42 @@ int main(int argc, char* argv[])
output_file_path = fs::u8path(command_line::get_arg(vm, arg_output_file));
else
output_file_path = config_folder / "export" / BLOCKCHAIN_RAW;
LOG_PRINT_L0("Export output file: " << output_file_path.string());
oxen::log::warning(logcat, "Export output file: {}", output_file_path.string());
LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)");
oxen::log::warning(logcat, "Initializing source blockchain (BlockchainDB)");
blockchain_objects_t blockchain_objects = {};
Blockchain *core_storage = &blockchain_objects.m_blockchain;
BlockchainDB *db = new_db();
if (db == NULL)
{
LOG_ERROR("Failed to initialize a database");
oxen::log::error(logcat, "Failed to initialize a database");
throw std::runtime_error("Failed to initialize a database");
}
LOG_PRINT_L0("database: LMDB");
oxen::log::warning(logcat, "database: LMDB");
auto filename = config_folder / db->get_db_name();
LOG_PRINT_L0("Loading blockchain from folder " << filename << " ...");
oxen::log::warning(logcat, "Loading blockchain from folder {} ...", filename);
try
{
db->open(filename, core_storage->nettype(), DBF_RDONLY);
}
catch (const std::exception& e)
{
LOG_PRINT_L0("Error opening database: " << e.what());
oxen::log::warning(logcat, "Error opening database: {}", e.what());
return 1;
}
r = core_storage->init(db, nullptr, nullptr, opt_testnet ? cryptonote::network_type::TESTNET : opt_devnet ? cryptonote::network_type::DEVNET : cryptonote::network_type::MAINNET);
if (core_storage->get_blockchain_pruning_seed() && !opt_blocks_dat)
{
LOG_PRINT_L0("Blockchain is pruned, cannot export");
oxen::log::warning(logcat, "Blockchain is pruned, cannot export");
return 1;
}
CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage");
LOG_PRINT_L0("Source blockchain storage initialized OK");
LOG_PRINT_L0("Exporting blockchain raw data...");
oxen::log::warning(logcat, "Source blockchain storage initialized OK");
oxen::log::warning(logcat, "Exporting blockchain raw data...");
if (opt_blocks_dat)
{
@ -165,7 +166,7 @@ int main(int argc, char* argv[])
r = bootstrap.store_blockchain_raw(core_storage, NULL, output_file_path, block_stop);
}
CHECK_AND_ASSERT_MES(r, 1, "Failed to export blockchain raw data");
LOG_PRINT_L0("Blockchain raw data exported OK");
oxen::log::warning(logcat, "Blockchain raw data exported OK");
return 0;
CATCH_ENTRY("Export error", 1);

View File

@ -36,6 +36,7 @@
#include <unistd.h>
#include "cryptonote_protocol/quorumnet.h"
#include "epee/misc_log_ex.h"
#include "logging/oxen_logger.h"
#include "bootstrap_file.h"
#include "bootstrap_serialization.h"
#include "blocks/blocks.h"
@ -44,9 +45,10 @@
#include "cryptonote_core/uptime_proof.h"
#include "cryptonote_core/cryptonote_core.h"
#include "common/hex.h"
#include <fmt/std.h>
#include <fmt/color.h>
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
static auto logcat = oxen::log::Cat("bcutil");
namespace
{
@ -142,8 +144,7 @@ int check_flush(cryptonote::core &core, std::vector<block_complete_entry> &block
cryptonote::block block;
if (!parse_and_validate_block_from_blob(b.block, block))
{
MERROR("Failed to parse block: "
<< tools::type_to_hex(get_blob_hash(b.block)));
oxen::log::error(logcat, "Failed to parse block: {}", tools::type_to_hex(get_blob_hash(b.block)));
core.cleanup_handle_incoming_blocks();
return 1;
}
@ -155,12 +156,12 @@ int check_flush(cryptonote::core &core, std::vector<block_complete_entry> &block
std::vector<block> pblocks;
if (!core.prepare_handle_incoming_blocks(blocks, pblocks))
{
MERROR("Failed to prepare to add blocks");
oxen::log::error(logcat, "Failed to prepare to add blocks");
return 1;
}
if (!pblocks.empty() && pblocks.size() != blocks.size())
{
MERROR("Unexpected parsed blocks size");
oxen::log::error(logcat, "Unexpected parsed blocks size");
core.cleanup_handle_incoming_blocks();
return 1;
}
@ -175,8 +176,7 @@ int check_flush(cryptonote::core &core, std::vector<block_complete_entry> &block
core.handle_incoming_tx(tx_blob, tvc, tx_pool_options::from_block());
if(tvc.m_verifivation_failed)
{
MERROR("transaction verification failed, tx_id = "
<< tools::type_to_hex(get_blob_hash(tx_blob)));
oxen::log::error(logcat, "transaction verification failed, tx_id = {}", tools::type_to_hex(get_blob_hash(tx_blob)));
core.cleanup_handle_incoming_blocks();
return 1;
}
@ -190,14 +190,13 @@ int check_flush(cryptonote::core &core, std::vector<block_complete_entry> &block
if(bvc.m_verifivation_failed)
{
MERROR("Block verification failed, id = "
<< tools::type_to_hex(get_blob_hash(block_entry.block)));
oxen::log::error(logcat, "Block verification failed, id = {}", tools::type_to_hex(get_blob_hash(block_entry.block)));
core.cleanup_handle_incoming_blocks();
return 1;
}
if(bvc.m_marked_as_orphaned)
{
MERROR("Block received at sync phase was marked as orphaned");
oxen::log::error(logcat, "Block received at sync phase was marked as orphaned");
core.cleanup_handle_incoming_blocks();
return 1;
}
@ -219,7 +218,7 @@ int import_from_file(cryptonote::core& core, const fs::path& import_file_path, u
if (std::error_code ec; !fs::exists(import_file_path, ec))
{
MFATAL("bootstrap file not found: " << import_file_path);
oxen::log::error(logcat, "bootstrap file not found: {}", import_file_path);
return false;
}
@ -232,7 +231,7 @@ int import_from_file(cryptonote::core& core, const fs::path& import_file_path, u
std::streampos pos;
// BootstrapFile bootstrap(import_file_path);
uint64_t total_source_blocks = bootstrap.count_blocks(import_file_path, pos, seek_height);
MINFO("bootstrap file last block number: " << total_source_blocks-1 << " (zero-based height) total blocks: " << total_source_blocks);
oxen::log::info(logcat, "bootstrap file last block number: {} (zero-based height) total blocks: {}", total_source_blocks-1, total_source_blocks);
if (total_source_blocks-1 <= start_height)
{
@ -245,7 +244,7 @@ int import_from_file(cryptonote::core& core, const fs::path& import_file_path, u
if (import_file.fail())
{
MFATAL("import_file.open() fail");
oxen::log::error(logcat, "import_file.open() fail");
return false;
}
@ -269,12 +268,11 @@ int import_from_file(cryptonote::core& core, const fs::path& import_file_path, u
// These are what we'll try to use, and they don't have to be a determination
// from source and destination blockchains, but those are the defaults.
MINFO("start block: " << start_height << " stop block: " <<
block_stop);
oxen::log::info(logcat, "start block: {} stop block: {}", start_height, block_stop);
bool use_batch = opt_batch && !opt_verify;
MINFO("Reading blockchain from bootstrap file...");
oxen::log::info(logcat, "Reading blockchain from bootstrap file...");
std::cout << "\n";
std::vector<block_complete_entry> blocks;
@ -313,7 +311,7 @@ int import_from_file(cryptonote::core& core, const fs::path& import_file_path, u
// TODO: bootstrap.read_chunk();
if (! import_file) {
std::cout << refresh_string;
MINFO("End of file reached");
oxen::log::info(logcat, "End of file reached");
quit = 1;
break;
}
@ -324,19 +322,19 @@ int import_from_file(cryptonote::core& core, const fs::path& import_file_path, u
} catch (const std::exception& e) {
throw std::runtime_error("Error in deserialization of chunk size: "s + e.what());
}
MDEBUG("chunk_size: " << chunk_size);
oxen::log::debug(logcat, "chunk_size: {}", chunk_size);
if (chunk_size > BUFFER_SIZE)
{
MWARNING("WARNING: chunk_size " << chunk_size << " > BUFFER_SIZE " << BUFFER_SIZE);
oxen::log::warning(logcat, "WARNING: chunk_size {} > BUFFER_SIZE {}", chunk_size, BUFFER_SIZE);
throw std::runtime_error("Aborting: chunk size exceeds buffer size");
}
if (chunk_size > CHUNK_SIZE_WARNING_THRESHOLD)
{
MINFO("NOTE: chunk_size " << chunk_size << " > " << CHUNK_SIZE_WARNING_THRESHOLD);
oxen::log::info(logcat, "NOTE: chunk_size {} > {}", chunk_size, CHUNK_SIZE_WARNING_THRESHOLD);
}
else if (chunk_size == 0) {
MFATAL("ERROR: chunk_size == 0");
oxen::log::error(logcat, "ERROR: chunk_size == 0");
return 2;
}
import_file.read(buffer_block, chunk_size);
@ -344,26 +342,25 @@ int import_from_file(cryptonote::core& core, const fs::path& import_file_path, u
if (import_file.eof())
{
std::cout << refresh_string;
MINFO("End of file reached - file was truncated");
oxen::log::info(logcat, "End of file reached - file was truncated");
quit = 1;
break;
}
else
{
MFATAL("ERROR: unexpected end of file: bytes read before error: "
<< import_file.gcount() << " of chunk_size " << chunk_size);
oxen::log::error(logcat, "ERROR: unexpected end of file: bytes read before error: {} of chunk_size {}", import_file.gcount(), chunk_size);
return 2;
}
}
bytes_read += chunk_size;
MDEBUG("Total bytes read: " << bytes_read);
oxen::log::debug(logcat, "Total bytes read: {}", bytes_read);
if (h > block_stop)
{
std::cout << refresh_string << "block " << h-1
<< " / " << block_stop
<< "\n" << std::endl;
MINFO("Specified block number reached - stopping. block: " << h-1 << " total blocks: " << h);
oxen::log::info(logcat, "Specified block number reached - stopping. block: {} total blocks: {}", h-1, h);
quit = 1;
break;
}
@ -386,14 +383,14 @@ int import_from_file(cryptonote::core& core, const fs::path& import_file_path, u
if ((h-1) % display_interval == 0)
{
std::cout << refresh_string;
MDEBUG("loading block number " << h-1);
oxen::log::debug(logcat, "loading block number {}", h-1);
}
else
{
MDEBUG("loading block number " << h-1);
oxen::log::debug(logcat, "loading block number {}", h-1);
}
b = bp.block;
MDEBUG("block prev_id: " << b.prev_id << "\n");
oxen::log::debug(logcat, "block prev_id: {}\n", b.prev_id);
if ((h-1) % progress_interval == 0)
{
@ -458,7 +455,7 @@ int import_from_file(cryptonote::core& core, const fs::path& import_file_path, u
catch (const std::exception& e)
{
std::cout << refresh_string;
MFATAL("Error adding block to blockchain: " << e.what());
oxen::log::error(logcat, "Error adding block to blockchain: {}", e.what());
quit = 2; // make sure we don't commit partial block data
break;
}
@ -488,7 +485,7 @@ int import_from_file(cryptonote::core& core, const fs::path& import_file_path, u
catch (const std::exception& e)
{
std::cout << refresh_string;
MFATAL("exception while reading from file, height=" << h << ": " << e.what());
oxen::log::error(logcat, "exception while reading from file, height={}: {}", h, e.what());
return 2;
}
} // while
@ -517,10 +514,10 @@ quitting:
}
core.get_blockchain_storage().get_db().show_stats();
MINFO("Number of blocks imported: " << num_imported);
oxen::log::info(logcat, "Number of blocks imported: {}", num_imported);
if (h > 0)
// TODO: if there was an error, the last added block is probably at zero-based height h-2
MINFO("Finished at block: " << h-1 << " total blocks: " << h);
oxen::log::info(logcat, "Finished at block: {} total blocks: {}", h-1, h);
std::cout << "\n";
return 0;
@ -532,7 +529,6 @@ int main(int argc, char* argv[])
epee::string_tools::set_module_name_and_folder(argv[0]);
uint32_t log_level = 0;
uint64_t num_blocks = 0;
uint64_t block_stop = 0;
std::string m_config_folder;
@ -638,14 +634,17 @@ int main(int argc, char* argv[])
return 1;
}
m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir);
auto log_file_path = m_config_folder + "oxen-blockchain-import.log";
oxen::log::Level log_level;
if(auto level = oxen::logging::parse_level(command_line::get_arg(vm, arg_log_level).c_str())) {
log_level = *level;
} else {
std::cerr << "Incorrect log level: " << command_line::get_arg(vm, arg_log_level).c_str() << std::endl;
throw std::runtime_error{"Incorrect log level"};
}
mlog_configure(mlog_get_default_log_path("oxen-blockchain-import.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else
mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str());
MINFO("Starting...");
oxen::logging::init(log_file_path, log_level);
oxen::log::info(logcat, "Starting...");
fs::path import_file_path;
@ -661,32 +660,31 @@ int main(int argc, char* argv[])
return 0;
}
MINFO("database: LMDB");
MINFO("verify: " << std::boolalpha << opt_verify << std::noboolalpha);
oxen::log::info(logcat, "database: LMDB");
oxen::log::info(logcat, "verify: {}", opt_verify);
if (opt_batch)
{
MINFO("batch: " << std::boolalpha << opt_batch << std::noboolalpha
<< " batch size: " << db_batch_size);
oxen::log::info(logcat, "batch: {} batch size: {}", opt_batch, db_batch_size);
}
else
{
MINFO("batch: " << std::boolalpha << opt_batch << std::noboolalpha);
oxen::log::info(logcat, "batch: {}", opt_batch);
}
MINFO("resume: " << std::boolalpha << opt_resume << std::noboolalpha);
MINFO("nettype: " << (opt_testnet ? "testnet" : opt_devnet ? "devnet" : "mainnet"));
oxen::log::info(logcat, "resume: {}", opt_resume);
oxen::log::info(logcat, "nettype: {}", (opt_testnet ? "testnet" : opt_devnet ? "devnet" : "mainnet"));
MINFO("bootstrap file path: " << import_file_path);
MINFO("database path: " << m_config_folder);
oxen::log::info(logcat, "bootstrap file path: {}", import_file_path);
oxen::log::info(logcat, "database path: {}", m_config_folder);
if (!opt_verify)
{
MCLOG_RED(el::Level::Warning, "global", "\n"
"Import is set to proceed WITHOUT VERIFICATION.\n"
"This is a DANGEROUS operation: if the file was tampered with in transit, or obtained from a malicious source,\n"
"you could end up with a compromised database. It is recommended to NOT use " << arg_noverify.name << ".\n"
"*****************************************************************************************\n"
"You have 90 seconds to press ^C or terminate this program before unverified import starts\n"
"*****************************************************************************************");
oxen::log::warning(logcat, fmt::format(fg(fmt::terminal_color::red), "\n\
Import is set to proceed WITHOUT VERIFICATION.\n\
This is a DANGEROUS operation: if the file was tampered with in transit, or obtained from a malicious source,\n\
you could end up with a compromised database. It is recommended to NOT use {}.\n\
*****************************************************************************************\n\
You have 90 seconds to press ^C or terminate this program before unverified import starts\n\
*****************************************************************************************", arg_noverify.name));
sleep(90);
}
@ -714,9 +712,9 @@ int main(int argc, char* argv[])
if (!command_line::is_arg_defaulted(vm, arg_pop_blocks))
{
num_blocks = command_line::get_arg(vm, arg_pop_blocks);
MINFO("height: " << core.get_blockchain_storage().get_current_blockchain_height());
oxen::log::info(logcat, "height: {}", core.get_blockchain_storage().get_current_blockchain_height());
pop_blocks(core, num_blocks);
MINFO("height: " << core.get_blockchain_storage().get_current_blockchain_height());
oxen::log::info(logcat, "height: {}", core.get_blockchain_storage().get_current_blockchain_height());
return 0;
}

View File

@ -39,8 +39,7 @@
#include "blockchain_objects.h"
#include "version.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
static auto logcat = oxen::log::Cat("bcutil");
#define MDB_val_set(var, val) MDB_val var = {sizeof(val), (void *)&val}
@ -57,7 +56,7 @@ static std::error_code replace_file(const fs::path& replacement_name, const fs::
{
std::error_code ec = fs::rename(replacement_name, replaced_name);
if (ec)
MERROR("Error renaming " << replacement_name << " to " << replaced_name << ": " << ec.message());
oxen::log::error(logcat, "Error renaming {} to {}: {}", replacement_name, replaced_name, ec.message());
return ec;
}
@ -94,7 +93,7 @@ static void add_size(MDB_env *env, uint64_t bytes)
auto si = fs::space(db_path);
if(si.available < bytes)
{
MERROR("!! WARNING: Insufficient free space to extend database !!: " <<
oxen::log::error(logcat, "!! WARNING: Insufficient free space to extend database !!: ",
(si.available >> 20L) << " MB available, " << (bytes >> 20L) << " MB needed");
return;
}
@ -102,7 +101,7 @@ static void add_size(MDB_env *env, uint64_t bytes)
catch(...)
{
// print something but proceed.
MWARNING("Unable to query free disk space.");
oxen::log::warning(logcat, "Unable to query free disk space.");
}
MDB_envinfo mei;
@ -117,7 +116,7 @@ static void add_size(MDB_env *env, uint64_t bytes)
if (result)
throw std::runtime_error("Failed to set new mapsize to " + std::to_string(new_mapsize) + ": " + std::string(mdb_strerror(result)));
MGINFO("LMDB Mapsize increased." << " Old: " << mei.me_mapsize / (1024 * 1024) << "MiB" << ", New: " << new_mapsize / (1024 * 1024) << "MiB");
oxen::log::info(logcat, "LMDB Mapsize increased. Old: {}MiB, New: {}MiB", mei.me_mapsize / (1024 * 1024), new_mapsize / (1024 * 1024));
}
static void check_resize(MDB_env *env, size_t bytes)
@ -154,7 +153,7 @@ static void copy_table(MDB_env *env0, MDB_env *env1, const char *table, unsigned
bool tx_active0 = false, tx_active1 = false;
int dbr;
MINFO("Copying " << table);
oxen::log::info(logcat, "Copying {}", table);
OXEN_DEFER {
if (tx_active1) mdb_txn_abort(txn1);
@ -251,7 +250,7 @@ static void prune(MDB_env *env0, MDB_env *env1)
bool tx_active0 = false, tx_active1 = false;
int dbr;
MGINFO("Creating pruned txs_prunable");
oxen::log::info(logcat, "Creating pruned txs_prunable");
OXEN_DEFER {
if (tx_active1) mdb_txn_abort(txn1);
@ -336,7 +335,7 @@ static void prune(MDB_env *env0, MDB_env *env1)
MDB_val_set(kk, ti->data.tx_id);
if (block_height + PRUNING_TIP_BLOCKS >= blockchain_height)
{
MDEBUG(block_height << "/" << blockchain_height << " is in tip");
oxen::log::debug(logcat, "{}/{} is in tip", block_height, blockchain_height);
MDB_val_set(vv, block_height);
dbr = mdb_cursor_put(cur1_txs_prunable_tip, &kk, &vv, 0);
if (dbr) throw std::runtime_error("Failed to write prunable tx tip data: " + std::string(mdb_strerror(dbr)));
@ -360,7 +359,7 @@ static void prune(MDB_env *env0, MDB_env *env1)
}
else
{
MDEBUG("" << block_height << "/" << blockchain_height << " should be pruned, dropping");
oxen::log::debug(logcat, "{}/{} should be pruned, dropping", block_height, blockchain_height);
}
}
@ -386,7 +385,7 @@ static bool parse_db_sync_mode(std::string db_sync_mode, uint64_t &db_flags)
auto options = tools::split_any(db_sync_mode, " :", true);
for(const auto &option : options)
MDEBUG("option: " << option);
oxen::log::debug(logcat, "option: {}", option);
// default to fast:async:1
uint64_t DEFAULT_FLAGS = DBF_FAST;
@ -490,7 +489,7 @@ int main(int argc, char* argv[])
else
mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str());
MINFO("Starting...");
oxen::log::info(logcat, "Starting...");
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
bool opt_devnet = command_line::get_arg(vm, cryptonote::arg_devnet_on);
@ -504,7 +503,7 @@ int main(int argc, char* argv[])
uint64_t db_flags = 0;
if (!parse_db_sync_mode(db_sync_mode, db_flags))
{
MERROR("Invalid db sync mode: " << db_sync_mode);
oxen::log::error(logcat, "Invalid db sync mode: {}", db_sync_mode);
return 1;
}
@ -519,7 +518,7 @@ int main(int argc, char* argv[])
// Blockchain* core_storage = new Blockchain(NULL);
// because unlike blockchain_storage constructor, which takes a pointer to
// tx_memory_pool, Blockchain's constructor takes tx_memory_pool object.
MINFO("Initializing source blockchain (BlockchainDB)");
oxen::log::info(logcat, "Initializing source blockchain (BlockchainDB)");
std::array<Blockchain *, 2> core_storage;
fs::path paths[2];
bool already_pruned = false;
@ -531,7 +530,7 @@ int main(int argc, char* argv[])
BlockchainDB* db = new_db();
if (db == NULL)
{
MERROR("Failed to initialize a database");
oxen::log::error(logcat, "Failed to initialize a database");
throw std::runtime_error("Failed to initialize a database");
}
@ -542,7 +541,7 @@ int main(int argc, char* argv[])
{
if (!fs::is_directory(paths[1]))
{
MERROR("LMDB needs a directory path, but a file was passed: " << paths[1].string());
oxen::log::error(logcat, "LMDB needs a directory path, but a file was passed: {}", paths[1].string());
return 1;
}
}
@ -550,7 +549,7 @@ int main(int argc, char* argv[])
{
if (!fs::create_directories(paths[1]))
{
MERROR("Failed to create directory: " << paths[1].string());
oxen::log::error(logcat, "Failed to create directory: {}", paths[1].string());
return 1;
}
}
@ -561,7 +560,7 @@ int main(int argc, char* argv[])
paths[0] = fs::u8path(data_dir) / db->get_db_name();
}
MINFO("Loading blockchain from folder " << paths[n] << " ...");
oxen::log::info(logcat, "Loading blockchain from folder {} ...", paths[n]);
try
{
@ -569,19 +568,19 @@ int main(int argc, char* argv[])
}
catch (const std::exception& e)
{
MERROR("Error opening database: " << e.what());
oxen::log::error(logcat, "Error opening database: {}", e.what());
return 1;
}
r = core_storage[n]->init(db, nullptr /*ons_db*/, net_type);
std::string source_dest = n == 0 ? "source" : "pruned";
CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize " << source_dest << " blockchain storage");
MINFO(source_dest << " blockchain storage initialized OK");
oxen::log::info(logcat, "{} blockchain storage initialized OK", source_dest);
if (n == 0 && core_storage[0]->get_blockchain_pruning_seed())
{
if (!opt_copy_pruned_database)
{
MERROR("Blockchain is already pruned, use --" << arg_copy_pruned_database.name << " to copy it anyway");
oxen::log::error(logcat, "Blockchain is already pruned, use --{} to copy it anyway", arg_copy_pruned_database.name);
return 1;
}
already_pruned = true;
@ -592,7 +591,7 @@ int main(int argc, char* argv[])
core_storage[1]->deinit();
delete core_storage[1];
MINFO("Pruning...");
oxen::log::info(logcat, "Pruning...");
MDB_env *env0 = NULL, *env1 = NULL;
open(env0, paths[0], db_flags, true);
open(env1, paths[1], db_flags, false);
@ -624,16 +623,16 @@ int main(int argc, char* argv[])
close(env1);
close(env0);
MINFO("Swapping databases, pre-pruning blockchain will be left in " << paths[0].string() + "-old and can be removed if desired");
oxen::log::info(logcat, "Swapping databases, pre-pruning blockchain will be left in {}", paths[0].string() + "-old and can be removed if desired");
fs::path old = paths[0];
old += "-old";
if (replace_file(paths[0], old) || replace_file(paths[1], paths[0]))
{
MERROR("Blockchain pruned OK, but renaming failed");
oxen::log::error(logcat, "Blockchain pruned OK, but renaming failed");
return 1;
}
MINFO("Blockchain pruned OK");
oxen::log::info(logcat, "Blockchain pruned OK");
return 0;
CATCH_ENTRY("Pruning error", 1);

View File

@ -37,8 +37,7 @@
#include "blockchain_db/blockchain_db.h"
#include "version.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
static auto logcat = oxen::log::Cat("bcutil");
namespace po = boost::program_options;
using namespace cryptonote;
@ -57,7 +56,7 @@ static std::map<uint64_t, uint64_t> load_outputs(const fs::path& filename)
if (!f)
{
MERROR("Failed to load outputs from " << filename << ": " << strerror(errno));
oxen::log::error(logcat, "Failed to load outputs from {}: {}", filename, strerror(errno));
return {};
}
while (1)
@ -80,7 +79,7 @@ static std::map<uint64_t, uint64_t> load_outputs(const fs::path& filename)
}
if (amount == std::numeric_limits<uint64_t>::max())
{
MERROR("Bad format in " << filename);
oxen::log::error(logcat, "Bad format in {}", filename);
continue;
}
if (sscanf(s, "%" PRIu64 "*%" PRIu64, &offset, &num_offsets) == 2 && num_offsets < std::numeric_limits<uint64_t>::max() - offset)
@ -93,7 +92,7 @@ static std::map<uint64_t, uint64_t> load_outputs(const fs::path& filename)
}
else
{
MERROR("Bad format in " << filename);
oxen::log::error(logcat, "Bad format in {}", filename);
continue;
}
}
@ -156,7 +155,7 @@ int main(int argc, char* argv[])
else
mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str());
LOG_PRINT_L0("Starting...");
oxen::log::warning(logcat, "Starting...");
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
bool opt_devnet = command_line::get_arg(vm, cryptonote::arg_devnet_on);
@ -166,18 +165,18 @@ int main(int argc, char* argv[])
const auto input = fs::u8path(command_line::get_arg(vm, arg_input));
LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)");
oxen::log::warning(logcat, "Initializing source blockchain (BlockchainDB)");
blockchain_objects_t blockchain_objects = {};
Blockchain *core_storage = &blockchain_objects.m_blockchain;
BlockchainDB *db = new_db();
if (db == NULL)
{
LOG_ERROR("Failed to initialize a database");
oxen::log::error(logcat, "Failed to initialize a database");
throw std::runtime_error("Failed to initialize a database");
}
const fs::path filename = fs::u8path(command_line::get_arg(vm, cryptonote::arg_data_dir)) / db->get_db_name();
LOG_PRINT_L0("Loading blockchain from folder " << filename << " ...");
oxen::log::warning(logcat, "Loading blockchain from folder {} ...", filename);
try
{
@ -185,20 +184,20 @@ int main(int argc, char* argv[])
}
catch (const std::exception& e)
{
LOG_PRINT_L0("Error opening database: " << e.what());
oxen::log::warning(logcat, "Error opening database: {}", e.what());
return 1;
}
r = core_storage->init(db, nullptr /*ons_db*/, net_type);
CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage");
LOG_PRINT_L0("Source blockchain storage initialized OK");
oxen::log::warning(logcat, "Source blockchain storage initialized OK");
std::map<uint64_t, uint64_t> known_spent_outputs;
if (input.empty())
{
std::map<uint64_t, std::pair<uint64_t, uint64_t>> outputs;
LOG_PRINT_L0("Scanning for known spent data...");
oxen::log::warning(logcat, "Scanning for known spent data...");
db->for_all_transactions([&](const crypto::hash &txid, const cryptonote::transaction &tx){
const bool miner_tx = tx.vin.size() == 1 && std::holds_alternative<txin_gen>(tx.vin[0]);
for (const auto &in: tx.vin)
@ -227,11 +226,11 @@ int main(int argc, char* argv[])
}
else
{
LOG_PRINT_L0("Loading known spent data...");
oxen::log::warning(logcat, "Loading known spent data...");
known_spent_outputs = load_outputs(input);
}
LOG_PRINT_L0("Pruning known spent data...");
oxen::log::warning(logcat, "Pruning known spent data...");
bool stop_requested = false;
tools::signal_handler::install([&stop_requested](int type) {
@ -249,22 +248,22 @@ int main(int argc, char* argv[])
if (i->first == 0)
{
if (opt_verbose)
MINFO("Ignoring output value " << i->first << ", with " << num_outputs << " outputs");
oxen::log::info(logcat, "Ignoring output value {}, with {} outputs", i->first, num_outputs);
continue;
}
num_eligible_outputs += num_outputs;
num_eligible_known_spent_outputs += i->second;
if (opt_verbose)
MINFO(i->first << ": " << i->second << "/" << num_outputs);
oxen::log::info(logcat, "{}: {}/{}", i->first, i->second, num_outputs);
if (num_outputs > i->second)
continue;
if (num_outputs && num_outputs < i->second)
{
MERROR("More outputs are spent than known for amount " << i->first << ", not touching");
oxen::log::error(logcat, "More outputs are spent than known for amount {}, not touching", i->first);
continue;
}
if (opt_verbose)
MINFO("Pruning data for " << num_outputs << " outputs");
oxen::log::info(logcat, "Pruning data for {} outputs", num_outputs);
if (!opt_dry_run)
db->prune_outputs(i->first);
num_prunable_outputs += i->second;
@ -272,13 +271,13 @@ int main(int argc, char* argv[])
db->batch_stop();
MINFO("Total outputs: " << num_total_outputs);
MINFO("Known spent outputs: " << num_known_spent_outputs);
MINFO("Eligible outputs: " << num_eligible_outputs);
MINFO("Eligible known spent outputs: " << num_eligible_known_spent_outputs);
MINFO("Prunable outputs: " << num_prunable_outputs);
oxen::log::info(logcat, "Total outputs: {}", num_total_outputs);
oxen::log::info(logcat, "Known spent outputs: {}", num_known_spent_outputs);
oxen::log::info(logcat, "Eligible outputs: {}", num_eligible_outputs);
oxen::log::info(logcat, "Eligible known spent outputs: {}", num_eligible_known_spent_outputs);
oxen::log::info(logcat, "Prunable outputs: {}", num_prunable_outputs);
LOG_PRINT_L0("Blockchain known spent data pruned OK");
oxen::log::warning(logcat, "Blockchain known spent data pruned OK");
core_storage->deinit();
return 0;

View File

@ -38,13 +38,12 @@
#include "version.h"
#include "cryptonote_core/uptime_proof.h"
#include <date/date.h>
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
#include <fmt/std.h>
namespace po = boost::program_options;
using namespace cryptonote;
static auto logcat = oxen::log::Cat("bcutil");
static bool stop_requested = false;
int main(int argc, char* argv[])
@ -52,11 +51,8 @@ int main(int argc, char* argv[])
TRY_ENTRY();
epee::string_tools::set_module_name_and_folder(argv[0]);
uint32_t log_level = 0;
uint64_t block_start = 0;
uint64_t block_stop = 0;
tools::on_startup();
auto opt_size = command_line::boost_option_sizes();
@ -104,13 +100,17 @@ int main(int argc, char* argv[])
return 1;
}
mlog_configure(mlog_get_default_log_path("oxen-blockchain-stats.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else
mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str());
LOG_PRINT_L0("Starting...");
auto m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir);
auto log_file_path = m_config_folder + "oxen-blockchain-stats.log";
oxen::log::Level log_level;
if(auto level = oxen::logging::parse_level(command_line::get_arg(vm, arg_log_level).c_str())) {
log_level = *level;
} else {
std::cerr << "Incorrect log level: " << command_line::get_arg(vm, arg_log_level).c_str() << std::endl;
throw std::runtime_error{"Incorrect log level"};
}
oxen::logging::init(log_file_path, log_level);
oxen::log::warning(logcat, "Starting...");
std::string opt_data_dir = command_line::get_arg(vm, cryptonote::arg_data_dir);
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
@ -123,18 +123,18 @@ int main(int argc, char* argv[])
bool do_ringsize = command_line::get_arg(vm, arg_ringsize);
bool do_hours = command_line::get_arg(vm, arg_hours);
LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)");
oxen::log::warning(logcat, "Initializing source blockchain (BlockchainDB)");
blockchain_objects_t blockchain_objects = {};
Blockchain *core_storage = &blockchain_objects.m_blockchain;
BlockchainDB *db = new_db();
if (db == NULL)
{
LOG_ERROR("Failed to initialize a database");
oxen::log::error(logcat, "Failed to initialize a database");
throw std::runtime_error("Failed to initialize a database");
}
const fs::path filename = fs::u8path(opt_data_dir) / db->get_db_name();
LOG_PRINT_L0("Loading blockchain from folder " << filename << " ...");
oxen::log::warning(logcat, "Loading blockchain from folder {} ...", filename);
try
{
@ -142,13 +142,13 @@ int main(int argc, char* argv[])
}
catch (const std::exception& e)
{
LOG_PRINT_L0("Error opening database: " << e.what());
oxen::log::warning(logcat, "Error opening database: {}", e.what());
return 1;
}
r = core_storage->init(db, nullptr /*ons_db*/, nullptr, net_type);
CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage");
LOG_PRINT_L0("Source blockchain storage initialized OK");
oxen::log::warning(logcat, "Source blockchain storage initialized OK");
tools::signal_handler::install([](int type) {
stop_requested = true;
@ -157,7 +157,7 @@ int main(int argc, char* argv[])
const uint64_t db_height = db->height();
if (!block_stop)
block_stop = db_height;
MINFO("Starting from height " << block_start << ", stopping at height " << block_stop);
oxen::log::info(logcat, "Starting from height {}, stopping at height {}", block_start, block_stop);
/*
* The default output can be plotted with GnuPlot using these commands:
@ -212,7 +212,7 @@ plot 'stats.csv' index "DATA" using (timecolumn(1,"%Y-%m-%d")):4 with lines, ''
cryptonote::block blk;
if (!cryptonote::parse_and_validate_block_from_blob(bd, blk))
{
LOG_PRINT_L0("Bad block from db");
oxen::log::warning(logcat, "Bad block from db");
return 1;
}
auto ts = std::chrono::system_clock::from_time_t(blk.timestamp);
@ -272,7 +272,7 @@ skip:
transaction tx;
if (!parse_and_validate_tx_base_from_blob(bd, tx))
{
LOG_PRINT_L0("Bad txn from db");
oxen::log::warning(logcat, "Bad txn from db");
return 1;
}
currsz += bd.size();

View File

@ -34,13 +34,13 @@
#include "blockchain_db/blockchain_db.h"
#include "cryptonote_core/uptime_proof.h"
#include "version.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
#include <fmt/std.h>
namespace po = boost::program_options;
using namespace cryptonote;
static auto logcat = oxen::log::Cat("quorum_cop");
struct output_data
{
uint64_t amount;
@ -78,11 +78,7 @@ int main(int argc, char* argv[])
TRY_ENTRY();
epee::string_tools::set_module_name_and_folder(argv[0]);
uint32_t log_level = 0;
tools::on_startup();
auto opt_size = command_line::boost_option_sizes();
po::options_description desc_cmd_only("Command line options", opt_size.first, opt_size.second);
@ -122,13 +118,17 @@ int main(int argc, char* argv[])
return 1;
}
mlog_configure(mlog_get_default_log_path("oxen-blockchain-usage.log"), true);
if (!command_line::is_arg_defaulted(vm, arg_log_level))
mlog_set_log(command_line::get_arg(vm, arg_log_level).c_str());
else
mlog_set_log(std::string(std::to_string(log_level) + ",bcutil:INFO").c_str());
LOG_PRINT_L0("Starting...");
auto m_config_folder = command_line::get_arg(vm, cryptonote::arg_data_dir);
auto log_file_path = m_config_folder + "oxen-blockchain-usage.log";
oxen::log::Level log_level;
if(auto level = oxen::logging::parse_level(command_line::get_arg(vm, arg_log_level).c_str())) {
log_level = *level;
} else {
std::cerr << "Incorrect log level: " << command_line::get_arg(vm, arg_log_level).c_str() << std::endl;
throw std::runtime_error{"Incorrect log level"};
}
oxen::logging::init(log_file_path, log_level);
oxen::log::warning(logcat, "Starting...");
bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
bool opt_devnet = command_line::get_arg(vm, cryptonote::arg_devnet_on);
@ -146,7 +146,7 @@ int main(int argc, char* argv[])
// Blockchain* core_storage = new Blockchain(NULL);
// because unlike blockchain_storage constructor, which takes a pointer to
// tx_memory_pool, Blockchain's constructor takes tx_memory_pool object.
LOG_PRINT_L0("Initializing source blockchain (BlockchainDB)");
oxen::log::warning(logcat, "Initializing source blockchain (BlockchainDB)");
const std::string input = command_line::get_arg(vm, arg_input);
blockchain_objects_t blockchain_objects = {};
Blockchain *core_storage = &blockchain_objects.m_blockchain;
@ -154,13 +154,13 @@ int main(int argc, char* argv[])
BlockchainDB *db = new_db();
if (db == NULL)
{
LOG_ERROR("Failed to initialize a database");
oxen::log::error(logcat, "Failed to initialize a database");
throw std::runtime_error("Failed to initialize a database");
}
LOG_PRINT_L0("database: LMDB");
oxen::log::warning(logcat, "database: LMDB");
const fs::path filename = fs::u8path(input);
LOG_PRINT_L0("Loading blockchain from folder " << filename << " ...");
oxen::log::warning(logcat, "Loading blockchain from folder {} ...", filename);
try
{
@ -168,22 +168,22 @@ int main(int argc, char* argv[])
}
catch (const std::exception& e)
{
LOG_PRINT_L0("Error opening database: " << e.what());
oxen::log::warning(logcat, "Error opening database: {}", e.what());
return 1;
}
r = core_storage->init(db, nullptr /*ons_db*/, nullptr, net_type);
CHECK_AND_ASSERT_MES(r, 1, "Failed to initialize source blockchain storage");
LOG_PRINT_L0("Source blockchain storage initialized OK");
oxen::log::warning(logcat, "Source blockchain storage initialized OK");
LOG_PRINT_L0("Building usage patterns...");
oxen::log::warning(logcat, "Building usage patterns...");
size_t done = 0;
std::unordered_map<output_data, std::list<reference>> outputs;
std::unordered_map<uint64_t,uint64_t> indices;
LOG_PRINT_L0("Reading blockchain from " << input);
oxen::log::warning(logcat, "Reading blockchain from {}", input);
core_storage->for_all_transactions([&](const crypto::hash &hash, const cryptonote::transaction &tx)->bool
{
const bool coinbase = tx.vin.size() == 1 && std::holds_alternative<txin_gen>(tx.vin[0]);
@ -228,15 +228,15 @@ int main(int argc, char* argv[])
for (const auto &c: counts)
{
float percent = 100.f * c.second / total;
MINFO(std::to_string(c.second) << " outputs used " << c.first << " times (" << percent << "%)");
oxen::log::info(logcat, "{} outputs used {} times ({}%)", std::to_string(c.second), c.first, percent);
}
}
else
{
MINFO("No outputs to process");
oxen::log::info(logcat, "No outputs to process");
}
LOG_PRINT_L0("Blockchain usage exported OK");
oxen::log::warning(logcat, "Blockchain usage exported OK");
return 0;
CATCH_ENTRY("Export error", 1);

View File

@ -28,9 +28,7 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "blocksdat_file.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
#include <fmt/std.h>
namespace po = boost::program_options;
@ -38,6 +36,8 @@ using namespace cryptonote;
namespace
{
static auto logcat = oxen::log::Cat("bcutil");
std::string refresh_string = "\r \r";
}
@ -52,7 +52,7 @@ bool BlocksdatFile::open_writer(const fs::path& file_path, uint64_t block_stop)
{
if (!fs::is_directory(dir_path))
{
MFATAL("export directory path is a file: " << dir_path);
oxen::log::error(logcat, "export directory path is a file: {}", dir_path);
return false;
}
}
@ -60,7 +60,7 @@ bool BlocksdatFile::open_writer(const fs::path& file_path, uint64_t block_stop)
{
if (!fs::create_directory(dir_path))
{
MFATAL("Failed to create directory " << dir_path);
oxen::log::error(logcat, "Failed to create directory {}", dir_path);
return false;
}
}
@ -68,7 +68,7 @@ bool BlocksdatFile::open_writer(const fs::path& file_path, uint64_t block_stop)
m_raw_data_file = new std::ofstream();
MINFO("creating file");
oxen::log::info(logcat, "creating file");
m_raw_data_file->open(file_path.string(), std::ios_base::binary | std::ios_base::out | std::ios::trunc);
if (m_raw_data_file->fail())
@ -133,21 +133,21 @@ bool BlocksdatFile::store_blockchain_raw(Blockchain* _blockchain_storage, tx_mem
uint64_t block_start = 0;
uint64_t block_stop = 0;
MINFO("source blockchain height: " << m_blockchain_storage->get_current_blockchain_height()-1);
oxen::log::info(logcat, "source blockchain height: {}", m_blockchain_storage->get_current_blockchain_height()-1);
if ((requested_block_stop > 0) && (requested_block_stop < m_blockchain_storage->get_current_blockchain_height()))
{
MINFO("Using requested block height: " << requested_block_stop);
oxen::log::info(logcat, "Using requested block height: {}", requested_block_stop);
block_stop = requested_block_stop;
}
else
{
block_stop = m_blockchain_storage->get_current_blockchain_height() - 1;
MINFO("Using block height of source blockchain: " << block_stop);
oxen::log::info(logcat, "Using block height of source blockchain: {}", block_stop);
}
MINFO("Storing blocks raw data...");
oxen::log::info(logcat, "Storing blocks raw data...");
if (!BlocksdatFile::open_writer(output_file, block_stop))
{
MFATAL("failed to open raw file for write");
oxen::log::error(logcat, "failed to open raw file for write");
return false;
}
for (m_cur_height = block_start; m_cur_height <= block_stop; ++m_cur_height)
@ -167,7 +167,7 @@ bool BlocksdatFile::store_blockchain_raw(Blockchain* _blockchain_storage, tx_mem
std::cout << refresh_string;
std::cout << "block " << m_cur_height-1 << "/" << block_stop << "\n";
MINFO("Number of blocks exported: " << num_blocks_written);
oxen::log::info(logcat, "Number of blocks exported: {}", num_blocks_written);
return BlocksdatFile::close();
}

View File

@ -29,11 +29,11 @@
#include "bootstrap_serialization.h"
#include "serialization/binary_utils.h" // dump_binary(), parse_binary()
#include <fmt/std.h>
#include "bootstrap_file.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "bcutil"
static auto logcat = oxen::log::Cat("bcutil");
namespace po = boost::program_options;
@ -60,7 +60,7 @@ bool BootstrapFile::open_writer(const fs::path& file_path)
{
if (!fs::is_directory(dir_path))
{
MFATAL("export directory path is a file: " << dir_path);
oxen::log::error(logcat, "export directory path is a file: {}", dir_path);
return false;
}
}
@ -68,7 +68,7 @@ bool BootstrapFile::open_writer(const fs::path& file_path)
{
if (!fs::create_directory(dir_path))
{
MFATAL("Failed to create directory " << dir_path);
oxen::log::error(logcat, "Failed to create directory {}", dir_path);
return false;
}
}
@ -81,14 +81,14 @@ bool BootstrapFile::open_writer(const fs::path& file_path)
if (! fs::exists(file_path))
{
MDEBUG("creating file");
oxen::log::debug(logcat, "creating file");
do_initialize_file = true;
num_blocks = 0;
}
else
{
num_blocks = count_blocks(file_path.string());
MDEBUG("appending to existing file with height: " << num_blocks-1 << " total blocks: " << num_blocks);
oxen::log::debug(logcat, "appending to existing file with height: {} total blocks: {}", num_blocks-1, num_blocks);
}
m_height = num_blocks;
@ -139,7 +139,7 @@ bool BootstrapFile::initialize_file()
uint32_t bd_size = 0;
std::string bd = t_serializable_object_to_blob(bfi);
MDEBUG("bootstrap::file_info size: " << bd.size());
oxen::log::debug(logcat, "bootstrap::file_info size: {}", bd.size());
bd_size = bd.size();
try {
@ -151,7 +151,7 @@ bool BootstrapFile::initialize_file()
output_stream_header << bd;
bd = t_serializable_object_to_blob(bbi);
MDEBUG("bootstrap::blocks_info size: " << bd.size());
oxen::log::debug(logcat, "bootstrap::blocks_info size: {}", bd.size());
bd_size = bd.size();
try {
@ -175,10 +175,10 @@ void BootstrapFile::flush_chunk()
m_output_stream->flush();
uint32_t chunk_size = m_buffer.size();
// MTRACE("chunk_size " << chunk_size);
// oxen::log::trace(logcat, "chunk_size {}", chunk_size);
if (chunk_size > BUFFER_SIZE)
{
MWARNING("WARNING: chunk_size " << chunk_size << " > BUFFER_SIZE " << BUFFER_SIZE);
oxen::log::warning(logcat, "WARNING: chunk_size {} > BUFFER_SIZE {}", chunk_size, BUFFER_SIZE);
}
std::string blob;
@ -200,14 +200,14 @@ void BootstrapFile::flush_chunk()
long num_chars_written = pos_after - pos_before;
if (static_cast<unsigned long>(num_chars_written) != chunk_size)
{
MFATAL("Error writing chunk: height: " << m_cur_height << " chunk_size: " << chunk_size << " num chars written: " << num_chars_written);
oxen::log::error(logcat, "Error writing chunk: height: {} chunk_size: {} num chars written: {}", m_cur_height, chunk_size, num_chars_written);
throw std::runtime_error("Error writing chunk");
}
m_buffer.clear();
delete m_output_stream;
m_output_stream = new boost::iostreams::stream<boost::iostreams::back_insert_device<buffer_type>>(m_buffer);
MDEBUG("flushed chunk: chunk_size: " << chunk_size);
oxen::log::debug(logcat, "flushed chunk: chunk_size: {}", chunk_size);
}
void BootstrapFile::write_block(block& block)
@ -271,10 +271,10 @@ bool BootstrapFile::store_blockchain_raw(Blockchain* _blockchain_storage, tx_mem
m_blockchain_storage = _blockchain_storage;
m_tx_pool = _tx_pool;
uint64_t progress_interval = 100;
MINFO("Storing blocks raw data...");
oxen::log::info(logcat, "Storing blocks raw data...");
if (!BootstrapFile::open_writer(output_file))
{
MFATAL("failed to open raw file for write");
oxen::log::error(logcat, "failed to open raw file for write");
return false;
}
block b;
@ -284,16 +284,16 @@ bool BootstrapFile::store_blockchain_raw(Blockchain* _blockchain_storage, tx_mem
// height.
uint64_t block_start = m_height;
uint64_t block_stop = 0;
MINFO("source blockchain height: " << m_blockchain_storage->get_current_blockchain_height()-1);
oxen::log::info(logcat, "source blockchain height: {}", m_blockchain_storage->get_current_blockchain_height()-1);
if ((requested_block_stop > 0) && (requested_block_stop < m_blockchain_storage->get_current_blockchain_height()))
{
MINFO("Using requested block height: " << requested_block_stop);
oxen::log::info(logcat, "Using requested block height: {}", requested_block_stop);
block_stop = requested_block_stop;
}
else
{
block_stop = m_blockchain_storage->get_current_blockchain_height() - 1;
MINFO("Using block height of source blockchain: " << block_stop);
oxen::log::info(logcat, "Using block height of source blockchain: {}", block_stop);
}
for (m_cur_height = block_start; m_cur_height <= block_stop; ++m_cur_height)
{
@ -319,9 +319,9 @@ bool BootstrapFile::store_blockchain_raw(Blockchain* _blockchain_storage, tx_mem
std::cout << refresh_string;
std::cout << "block " << m_cur_height-1 << "/" << block_stop << "\n";
MINFO("Number of blocks exported: " << num_blocks_written);
oxen::log::info(logcat, "Number of blocks exported: {}", num_blocks_written);
if (num_blocks_written > 0)
MINFO("Largest chunk: " << m_max_chunk << " bytes");
oxen::log::info(logcat, "Largest chunk: {} bytes", m_max_chunk);
return BootstrapFile::close();
}
@ -345,11 +345,11 @@ uint64_t BootstrapFile::seek_to_first_chunk(fs::ifstream& import_file)
if (file_magic != blockchain_raw_magic)
{
MFATAL("bootstrap file not recognized");
oxen::log::error(logcat, "bootstrap file not recognized");
throw std::runtime_error("Aborting");
}
else
MINFO("bootstrap file recognized");
oxen::log::info(logcat, "bootstrap file recognized");
uint32_t buflen_file_info;
@ -362,7 +362,7 @@ uint64_t BootstrapFile::seek_to_first_chunk(fs::ifstream& import_file)
} catch (const std::exception& e) {
throw std::runtime_error("Error in deserialization of buflen_file_info: "s + e.what());
}
MINFO("bootstrap::file_info size: " << buflen_file_info);
oxen::log::info(logcat, "bootstrap::file_info size: {}", buflen_file_info);
if (buflen_file_info > sizeof(buf1))
throw std::runtime_error("Error: bootstrap::file_info size exceeds buffer size");
@ -376,9 +376,9 @@ uint64_t BootstrapFile::seek_to_first_chunk(fs::ifstream& import_file)
} catch (const std::exception& e) {
throw std::runtime_error("Error in deserialization of bootstrap::file_info: "s + e.what());
}
MINFO("bootstrap file v" << unsigned(bfi.major_version) << "." << unsigned(bfi.minor_version));
MINFO("bootstrap magic size: " << sizeof(file_magic));
MINFO("bootstrap header size: " << bfi.header_size);
oxen::log::info(logcat, "bootstrap file v{}.{}", unsigned(bfi.major_version), unsigned(bfi.minor_version));
oxen::log::info(logcat, "bootstrap magic size: {}", sizeof(file_magic));
oxen::log::info(logcat, "bootstrap header size: {}", bfi.header_size);
uint64_t full_header_size = sizeof(file_magic) + bfi.header_size;
import_file.seekg(full_header_size);
@ -398,7 +398,7 @@ uint64_t BootstrapFile::count_bytes(fs::ifstream& import_file, uint64_t blocks,
import_file.read(buf1, sizeof(chunk_size));
if (!import_file) {
std::cout << refresh_string;
MDEBUG("End of file reached");
oxen::log::debug(logcat, "End of file reached");
quit = true;
break;
}
@ -409,32 +409,29 @@ uint64_t BootstrapFile::count_bytes(fs::ifstream& import_file, uint64_t blocks,
} catch (const std::exception& e) {
throw std::runtime_error("Error in deserialization of chunk_size: "s + e.what());
}
MDEBUG("chunk_size: " << chunk_size);
oxen::log::debug(logcat, "chunk_size: {}", chunk_size);
if (chunk_size > BUFFER_SIZE)
{
std::cout << refresh_string;
MWARNING("WARNING: chunk_size " << chunk_size << " > BUFFER_SIZE " << BUFFER_SIZE
<< " height: " << h-1 << ", offset " << bytes_read);
oxen::log::warning(logcat, "WARNING: chunk_size {} > BUFFER_SIZE {} height: {}, offset {}", chunk_size, BUFFER_SIZE, h-1, bytes_read);
throw std::runtime_error("Aborting: chunk size exceeds buffer size");
}
if (chunk_size > CHUNK_SIZE_WARNING_THRESHOLD)
{
std::cout << refresh_string;
MDEBUG("NOTE: chunk_size " << chunk_size << " > " << CHUNK_SIZE_WARNING_THRESHOLD << " << height: "
<< h-1 << ", offset " << bytes_read);
oxen::log::debug(logcat, "NOTE: chunk_size {} > {} height: {}, offset {}", chunk_size, CHUNK_SIZE_WARNING_THRESHOLD, h-1, bytes_read);
}
else if (chunk_size <= 0) {
std::cout << refresh_string;
MDEBUG("ERROR: chunk_size " << chunk_size << " <= 0" << " height: " << h-1 << ", offset " << bytes_read);
oxen::log::debug(logcat, "ERROR: chunk_size {} <= 0 height: {}, offset {}", chunk_size, h-1, bytes_read);
throw std::runtime_error("Aborting");
}
// skip to next expected block size value
import_file.seekg(chunk_size, std::ios_base::cur);
if (! import_file) {
std::cout << refresh_string;
MFATAL("ERROR: unexpected end of file: bytes read before error: "
<< import_file.gcount() << " of chunk_size " << chunk_size);
oxen::log::error(logcat, "ERROR: unexpected end of file: bytes read before error: {} of chunk_size {}", import_file.gcount(), chunk_size);
throw std::runtime_error("Aborting");
}
bytes_read += chunk_size;
@ -459,7 +456,7 @@ uint64_t BootstrapFile::count_blocks(const fs::path& import_file_path, std::stre
{
if (std::error_code ec; !fs::exists(import_file_path, ec))
{
MFATAL("bootstrap file not found: " << import_file_path);
oxen::log::error(logcat, "bootstrap file not found: {}", import_file_path);
throw std::runtime_error("Aborting");
}
fs::ifstream import_file{import_file_path, std::ios::binary};
@ -468,14 +465,14 @@ uint64_t BootstrapFile::count_blocks(const fs::path& import_file_path, std::stre
uint64_t h = 0;
if (import_file.fail())
{
MFATAL("import_file.open() fail");
oxen::log::error(logcat, "import_file.open() fail");
throw std::runtime_error("Aborting");
}
uint64_t full_header_size; // 4 byte magic + length of header structures
full_header_size = seek_to_first_chunk(import_file);
MINFO("Scanning blockchain from bootstrap file...");
oxen::log::info(logcat, "Scanning blockchain from bootstrap file...");
bool quit = false;
uint64_t bytes_read = 0, blocks;
int progress_interval = 10;
@ -495,7 +492,7 @@ uint64_t BootstrapFile::count_blocks(const fs::path& import_file_path, std::stre
std::flush;
// std::cout << refresh_string;
MDEBUG("Number bytes scanned: " << bytes_read);
oxen::log::debug(logcat, "Number bytes scanned: {}", bytes_read);
}
import_file.close();

View File

@ -38,4 +38,5 @@ target_link_libraries(checkpoints
Boost::program_options
Boost::serialization
filesystem
logging
extra)

View File

@ -42,17 +42,20 @@
#include "common/oxen.h"
#include "common/file.h"
#include "common/hex.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "checkpoints"
#include <fmt/std.h>
namespace cryptonote
{
static auto logcat = oxen::log::Cat("checkpoints");
bool checkpoint_t::check(crypto::hash const &hash) const
{
bool result = block_hash == hash;
if (result) MINFO ("CHECKPOINT PASSED FOR HEIGHT " << height << " " << block_hash);
else MWARNING("CHECKPOINT FAILED FOR HEIGHT " << height << ". EXPECTED HASH " << block_hash << "GIVEN HASH: " << hash);
if (result)
oxen::log::info(logcat, "CHECKPOINT PASSED FOR HEIGHT {} {}", height, block_hash);
else
oxen::log::warning(logcat, "CHECKPOINT FAILED FOR HEIGHT {}. EXPECTED HASH {}GIVEN HASH: {}", height, block_hash, hash);
return result;
};
@ -93,7 +96,7 @@ namespace cryptonote
{
if (std::error_code ec; !fs::exists(json_hashfile_fullpath, ec))
{
LOG_PRINT_L1("Blockchain checkpoints file not found");
oxen::log::info(logcat, "Blockchain checkpoints file not found");
return true;
}
@ -102,7 +105,7 @@ namespace cryptonote
!tools::slurp_file(json_hashfile_fullpath, contents) ||
!epee::serialization::load_t_from_json(hashes, contents))
{
MERROR("Error loading checkpoints from " << json_hashfile_fullpath);
oxen::log::error(logcat, "Error loading checkpoints from {}", json_hashfile_fullpath);
return false;
}
@ -119,7 +122,7 @@ namespace cryptonote
}
catch (const std::exception &e)
{
MERROR("Get block checkpoint from DB failed at height: " << height << ", what = " << e.what());
oxen::log::error(logcat, "Get block checkpoint from DB failed at height: {}, what = {}", height, e.what());
return false;
}
}
@ -158,7 +161,7 @@ namespace cryptonote
}
catch (const std::exception& e)
{
MERROR("Failed to add checkpoint with hash: " << checkpoint.block_hash << " at height: " << checkpoint.height << ", what = " << e.what());
oxen::log::error(logcat, "Failed to add checkpoint with hash: {} at height: {}, what = {}", checkpoint.block_hash, checkpoint.height, e.what());
result = false;
}
@ -199,7 +202,7 @@ namespace cryptonote
}
catch (const std::exception &e)
{
MERROR("Pruning block checkpoint on block added failed non-trivially at height: " << m_last_cull_height << ", what = " << e.what());
oxen::log::error(logcat, "Pruning block checkpoint on block added failed non-trivially at height: {}, what = {}", m_last_cull_height, e.what());
}
}
@ -226,7 +229,7 @@ namespace cryptonote
}
catch (const std::exception &e)
{
MERROR("Remove block checkpoint on detach failed non-trivially at height: " << delete_height << ", what = " << e.what());
oxen::log::error(logcat, "Remove block checkpoint on detach failed non-trivially at height: {}, what = {}", delete_height, e.what());
}
}
}

View File

@ -31,7 +31,6 @@
#pragma once
#include <vector>
#include "epee/misc_log_ex.h"
#include "crypto/hash.h"
#include "cryptonote_config.h"
#include "cryptonote_core/service_node_voting.h"

View File

@ -39,7 +39,6 @@ add_library(common
oxen.cpp
notify.cpp
password.cpp
perf_timer.cpp
pruning.cpp
random.cpp
rules.cpp
@ -67,7 +66,7 @@ target_link_libraries(common
filesystem
fmt::fmt
date::date
fmt::fmt
PRIVATE
sodium
logging
extra)

View File

@ -34,7 +34,7 @@
#include <vector>
#include <functional>
#include "epee/misc_log_ex.h"
#include "logging/oxen_logger.h"
namespace tools
{
@ -44,7 +44,12 @@ void apply_permutation(std::vector<size_t> permutation, const F &swap)
{
//sanity check
for (size_t n = 0; n < permutation.size(); ++n)
CHECK_AND_ASSERT_THROW_MES(std::find(permutation.begin(), permutation.end(), n) != permutation.end(), "Bad permutation");
if (std::find(permutation.begin(), permutation.end(), n) == permutation.end())
{
oxen::log::error(globallogcat, "Bad permutation");
throw std::runtime_error("Bad permutation");
return;
}
for (size_t i = 0; i < permutation.size(); ++i)
{
@ -63,7 +68,12 @@ void apply_permutation(std::vector<size_t> permutation, const F &swap)
template<typename T>
void apply_permutation(const std::vector<size_t> &permutation, std::vector<T> &v)
{
CHECK_AND_ASSERT_THROW_MES(permutation.size() == v.size(), "Mismatched vector sizes");
if (permutation.size() != v.size())
{
oxen::log::error(globallogcat, "Mismatched vector sizes");
throw std::runtime_error("Mismatched vector sizes");
return;
}
apply_permutation(permutation, [&v](size_t i0, size_t i1){ std::swap(v[i0], v[i1]); });
}

View File

@ -30,11 +30,12 @@
#pragma once
#include "epee/misc_log_ex.h"
#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/portable_binary_oarchive.hpp>
#include <boost/archive/portable_binary_iarchive.hpp>
#include "epee/misc_log_ex.h"
#include "fs.h"
#include <fstream>
namespace tools

View File

@ -34,16 +34,20 @@
#include <sstream>
#include <array>
#include <type_traits>
#include <iostream>
#include <boost/program_options/parsers.hpp>
#include <boost/program_options/options_description.hpp>
#include <boost/program_options/variables_map.hpp>
#include "epee/misc_log_ex.h"
#include "common/string_util.h"
#include "common/i18n.h"
#include "logging/oxen_logger.h"
namespace command_line
{
static auto logcat = oxen::log::Cat("global");
inline const char* tr(const char* str) { return i18n_translate(str, "command_line"); }
/// @return True if `str` is (case-insensitively) y, yes, a potentially translated yes, or any of
@ -216,7 +220,8 @@ namespace command_line
{
if (0 != description.find_nothrow(arg.name, false))
{
CHECK_AND_ASSERT_MES(!unique, void(), "Argument already exists: " << arg.name);
if (!unique)
oxen::log::error(logcat, "Argument already exists: {}", arg.name);
return;
}
@ -228,7 +233,8 @@ namespace command_line
{
if (0 != description.find_nothrow(arg.name, false))
{
CHECK_AND_ASSERT_MES(!unique, void(), "Argument already exists: " << arg.name);
if (!unique)
oxen::log::error(logcat, "Argument already exists: {}", arg.name);
return;
}
@ -240,7 +246,8 @@ namespace command_line
{
if (0 != description.find_nothrow(arg.name, false))
{
CHECK_AND_ASSERT_MES(!unique, void(), "Argument already exists: " << arg.name);
if (!unique)
oxen::log::error(logcat, "Argument already exists: {}", arg.name);
return;
}

View File

@ -26,8 +26,8 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "expect.h"
#include "common/fs.h"
#include <easylogging++.h>
#include <string>
namespace detail
@ -48,9 +48,7 @@ namespace detail
error_msg.append("thrown at ");
// remove path, get just filename + extension
char buff[256] = {0};
el::base::utils::File::buildBaseFilename(file, buff, sizeof(buff) - 1);
error_msg.append(buff);
error_msg.append(fs::path(file).filename().c_str());
error_msg.push_back(':');
error_msg.append(std::to_string(line));

View File

@ -30,9 +30,11 @@
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
//
#include "file.h"
#include "epee/misc_log_ex.h"
#include "logging/oxen_logger.h"
#include <fmt/std.h>
#include <unistd.h>
#include <cstdio>
#include <fstream>
#ifdef WIN32
#include "epee/string_tools.h"
@ -59,11 +61,10 @@
#include "cryptonote_config.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "util"
namespace tools {
static auto logcat = oxen::log::Cat("util");
#ifndef _WIN32
static int flock_exnb(int fd)
{
@ -77,7 +78,7 @@ namespace tools {
fl.l_len = 0;
ret = fcntl(fd, F_SETLK, &fl);
if (ret < 0)
MERROR("Error locking fd " << fd << ": " << errno << " (" << strerror(errno) << ")");
oxen::log::error(logcat, "Error locking fd {}: {} ({})", fd, errno, strerror(errno));
return ret;
}
#endif
@ -207,14 +208,14 @@ namespace tools {
memset(&ov, 0, sizeof(ov));
if (!LockFileEx(m_fd, LOCKFILE_FAIL_IMMEDIATELY | LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &ov))
{
MERROR("Failed to lock " << filename << ": " << std::error_code(GetLastError(), std::system_category()));
oxen::log::error(logcat, "Failed to lock {}: {}", filename, std::error_code(GetLastError(), std::system_category()));
CloseHandle(m_fd);
m_fd = INVALID_HANDLE_VALUE;
}
}
else
{
MERROR("Failed to open " << filename << ": " << std::error_code(GetLastError(), std::system_category()));
oxen::log::error(logcat, "Failed to open {}: {}", filename, std::error_code(GetLastError(), std::system_category()));
}
#else
m_fd = open(filename.c_str(), O_RDWR | O_CREAT | O_CLOEXEC, 0666);
@ -222,14 +223,14 @@ namespace tools {
{
if (flock_exnb(m_fd) == -1)
{
MERROR("Failed to lock " << filename << ": " << std::strerror(errno));
oxen::log::error(logcat, "Failed to lock {}: {}", filename, std::strerror(errno));
close(m_fd);
m_fd = -1;
}
}
else
{
MERROR("Failed to open " << filename << ": " << std::strerror(errno));
oxen::log::error(logcat, "Failed to open {}: {}", filename, std::strerror(errno));
}
#endif
}
@ -264,7 +265,7 @@ namespace tools {
return fs::path{psz_path};
}
LOG_ERROR("SHGetSpecialFolderPathW() failed, could not obtain requested path.");
oxen::log::error(logcat, "SHGetSpecialFolderPathW() failed, could not obtain requested path.");
return "";
}
#endif
@ -302,17 +303,11 @@ namespace tools {
bool slurp_file(const fs::path& filename, std::string& contents)
{
fs::ifstream in;
in.exceptions(std::ifstream::failbit | std::ifstream::badbit);
try {
in.open(filename, std::ios::binary | std::ios::in | std::ios::ate);
contents.clear();
contents.resize(in.tellg());
in.seekg(0);
in.read(contents.data(), contents.size());
auto bytes_read = in.gcount();
if (static_cast<size_t>(bytes_read) < contents.size())
contents.resize(bytes_read);
fs::ifstream in(filename);
std::string content((std::istreambuf_iterator<char>(in)), (std::istreambuf_iterator<char>()));
contents = std::move(content);
return true;
} catch (...) {
return false;

View File

@ -37,9 +37,9 @@
#include <utility>
#include <algorithm>
#include "file.h"
#include <logging/oxen_logger.h>
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "i18n"
static auto logcat = oxen::log::Cat("i18n");
#define MAX_LANGUAGE_SIZE 16

View File

@ -41,13 +41,13 @@
} \
else \
{ \
LOG_ERROR("Field " << #name << " found in JSON, but not " << #jtype); \
oxen::log::error(logcat, "Field {} found in JSON, but not {}", #name, #jtype); \
return false; \
} \
} \
else if (mandatory) \
{ \
LOG_ERROR("Field " << #name << " not found in JSON"); \
oxen::log::error(logcat, "Field {} not found in JSON", #name); \
return false; \
} while(0)

View File

@ -28,15 +28,15 @@
#include "string_util.h"
#include "epee/misc_log_ex.h"
#include "logging/oxen_logger.h"
#include "spawn.h"
#include "notify.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "notify"
namespace tools
{
static auto logcat = oxen::log::Cat("notify");
/*
TODO:
- Improve tokenization to handle paths containing whitespaces, quotes, etc.

View File

@ -1,141 +0,0 @@
// Copyright (c) 2016-2019, The Monero Project
// Copyright (c) 2018, The Loki Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <chrono>
#include <vector>
#include "perf_timer.h"
using namespace std::literals;
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "perf"
#define PERF_LOG_ALWAYS(level, cat, x) \
el::base::Writer(level, __FILE__, __LINE__, ELPP_FUNC, el::base::DispatchAction::FileOnlyLog).construct(cat) << x
namespace tools
{
el::Level performance_timer_log_level = el::Level::Info;
static thread_local std::vector<LoggingPerformanceTimer*>* performance_timers = nullptr;
void set_performance_timer_log_level(el::Level level)
{
if (level != el::Level::Debug && level != el::Level::Trace && level != el::Level::Info
&& level != el::Level::Warning && level != el::Level::Error && level != el::Level::Fatal)
{
MERROR("Wrong log level: " << el::LevelHelper::convertToString(level) << ", using Info");
level = el::Level::Info;
}
performance_timer_log_level = level;
}
PerformanceTimer::PerformanceTimer(bool paused): started(true)
{
if (!paused)
since = std::chrono::steady_clock::now();
}
LoggingPerformanceTimer::LoggingPerformanceTimer(const std::string &s, const std::string &cat, uint64_t unit, el::Level l): PerformanceTimer(), name(s), cat(cat), unit(unit), level(l)
{
const bool log = ELPP->vRegistry()->allowed(level, cat.c_str());
if (!performance_timers)
{
if (log)
PERF_LOG_ALWAYS(level, cat.c_str(), "PERF ----------");
performance_timers = new std::vector<LoggingPerformanceTimer*>();
performance_timers->reserve(16); // how deep before realloc
}
else
{
LoggingPerformanceTimer* pt = performance_timers->back();
if (!pt->started && pt->since)
{
if (log)
{
size_t size = 0; for (const auto *tmp: *performance_timers) if (tmp->since) ++size;
PERF_LOG_ALWAYS(pt->level, cat.c_str(), "PERF " << std::string((size-1) * 2, ' ') << " " << pt->name);
}
pt->started = true;
}
}
performance_timers->push_back(this);
}
LoggingPerformanceTimer::~LoggingPerformanceTimer()
{
pause();
performance_timers->pop_back();
const bool log = ELPP->vRegistry()->allowed(level, cat.c_str());
if (log)
{
char s[12];
snprintf(s, sizeof(s), "%8llu ", static_cast<unsigned long long>(elapsed.count() / (1000000000 / unit)));
size_t size = 0; for (const auto *tmp: *performance_timers) if (tmp->since || tmp==this) ++size;
PERF_LOG_ALWAYS(level, cat.c_str(), "PERF " << s << std::string(size * 2, ' ') << " " << name);
}
if (performance_timers->empty())
{
delete performance_timers;
performance_timers = nullptr;
}
}
void PerformanceTimer::pause()
{
if (!since)
return;
auto now = std::chrono::steady_clock::now();
elapsed += now - *since;
since.reset();
}
void PerformanceTimer::resume()
{
if (!since)
since = std::chrono::steady_clock::now();
}
void PerformanceTimer::reset()
{
elapsed = 0ns;
if (since)
since = std::chrono::steady_clock::now();
}
std::chrono::nanoseconds PerformanceTimer::value() const
{
auto ret = elapsed;
if (since)
ret += std::chrono::steady_clock::now() - *since;
return ret;
}
} // namespace tools

View File

@ -1,84 +0,0 @@
// Copyright (c) 2016-2019, The Monero Project
// Copyright (c) 2018, The Loki Project
//
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without modification, are
// permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this list of
// conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice, this list
// of conditions and the following disclaimer in the documentation and/or other
// materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its contributors may be
// used to endorse or promote products derived from this software without specific
// prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#pragma once
#include <optional>
#include <string>
#include <cstdio>
#include <cstdint>
#include "epee/misc_log_ex.h"
namespace tools
{
extern el::Level performance_timer_log_level;
class PerformanceTimer
{
public:
PerformanceTimer(bool paused = false);
void pause();
void resume();
void reset();
std::chrono::nanoseconds value() const;
std::chrono::duration<double> seconds() const { return value(); }
protected:
std::optional<std::chrono::steady_clock::time_point> since;
std::chrono::nanoseconds elapsed;
bool started;
};
class LoggingPerformanceTimer: public PerformanceTimer
{
public:
LoggingPerformanceTimer(const std::string &s, const std::string &cat, uint64_t unit, el::Level l = el::Level::Info);
~LoggingPerformanceTimer();
private:
std::string name;
std::string cat;
uint64_t unit;
el::Level level;
};
void set_performance_timer_log_level(el::Level level);
#define PERF_TIMER_UNIT(name, unit) tools::LoggingPerformanceTimer pt_##name(#name, "perf." OXEN_DEFAULT_LOG_CATEGORY, unit, tools::performance_timer_log_level)
#define PERF_TIMER_UNIT_L(name, unit, l) tools::LoggingPerformanceTimer pt_##name(#name, "perf." OXEN_DEFAULT_LOG_CATEGORY, unit, l)
#define PERF_TIMER(name) PERF_TIMER_UNIT(name, 1000000)
#define PERF_TIMER_L(name, l) PERF_TIMER_UNIT_L(name, 1000000, l)
#define PERF_TIMER_START_UNIT(name, unit) std::unique_ptr<tools::LoggingPerformanceTimer> pt_##name(new tools::LoggingPerformanceTimer(#name, "perf." OXEN_DEFAULT_LOG_CATEGORY, unit, el::Level::Info))
#define PERF_TIMER_START(name) PERF_TIMER_START_UNIT(name, 1000000)
#define PERF_TIMER_STOP(name) do { pt_##name.reset(NULL); } while(0)
#define PERF_TIMER_PAUSE(name) pt_##name->pause()
#define PERF_TIMER_RESUME(name) pt_##name->resume()
}

View File

@ -1,23 +1,16 @@
#include "scoped_message_writer.h"
static auto logcat = oxen::log::Cat("msgwriter");
tools::scoped_message_writer::~scoped_message_writer()
{
if (m_flush)
{
m_flush = false;
MCLOG_FILE(m_log_level, "msgwriter", m_oss.str());
if (epee::console_color_default == m_color)
{
std::cout << m_oss.str();
}
if (fmt::terminal_color::white == m_color)
logcat->log(m_log_level, m_oss.str());
else
{
rdln::suspend_readline pause_readline;
set_console_color(m_color, m_bright);
std::cout << m_oss.str();
epee::reset_console_color();
}
logcat->log(m_log_level, fmt::format(fg(m_color),m_oss.str()));
std::cout << std::endl;
}
}

View File

@ -28,9 +28,11 @@
#pragma once
#include "epee/misc_log_ex.h"
#include "epee/readline_suspend.h"
#include "epee/misc_log_ex.h"
#include <iostream>
#include "logging/oxen_logger.h"
#include <fmt/color.h>
namespace tools
{
@ -43,19 +45,16 @@ class scoped_message_writer
private:
bool m_flush;
std::ostringstream m_oss;
epee::console_colors m_color;
bool m_bright;
el::Level m_log_level;
fmt::terminal_color m_color;
oxen::log::Level m_log_level;
public:
scoped_message_writer(
epee::console_colors color = epee::console_color_default
, bool bright = false
fmt::terminal_color color = fmt::terminal_color::white
, std::string prefix = {}
, el::Level log_level = el::Level::Info
, spdlog::level::level_enum log_level = spdlog::level::info
)
: m_flush(true)
, m_color(color)
, m_bright(bright)
, m_log_level(log_level)
{
m_oss << prefix;
@ -86,17 +85,17 @@ public:
inline scoped_message_writer success_msg_writer(bool color = true)
{
return scoped_message_writer(color ? epee::console_color_green : epee::console_color_default, false, std::string(), el::Level::Info);
return scoped_message_writer(color ? fmt::terminal_color::green : fmt::terminal_color::white, std::string(), spdlog::level::info);
}
inline scoped_message_writer msg_writer(epee::console_colors color = epee::console_color_default)
inline scoped_message_writer msg_writer(fmt::terminal_color color = fmt::terminal_color::white)
{
return scoped_message_writer(color, false, std::string(), el::Level::Info);
return scoped_message_writer(color, std::string(), spdlog::level::info);
}
inline scoped_message_writer fail_msg_writer()
{
return scoped_message_writer(epee::console_color_red, true, "Error: ", el::Level::Error);
return scoped_message_writer(fmt::terminal_color::red, "Error: ", spdlog::level::err);
}
} // namespace tools

View File

@ -47,7 +47,7 @@ namespace tools {
}
else
{
MGINFO_RED("Got control signal " << type << ". Exiting without saving...");
oxen::log::info(logcat, fmt::format(fg(fmt::terminal_color::red), "Got control signal {}. Exiting without saving...", type);
return FALSE;
}
return TRUE;

View File

@ -37,17 +37,17 @@
#endif
#include "epee/misc_log_ex.h"
#include "logging/oxen_logger.h"
#include "util.h"
#include "spawn.h"
#include "oxen.h"
#include "string_util.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "spawn"
namespace tools
{
static auto logcat = oxen::log::Cat("spawn");
#ifndef _WIN32
static void closefrom(int fd)
{
@ -83,7 +83,7 @@ int spawn(const fs::path& filename, const std::vector<std::string>& args, bool w
// wchar_t* but out input is utf-8). Shame on you for this garbage API, Windows.
if (!CreateProcessA(filename.string().c_str(), commandLine, nullptr, nullptr, false, 0, nullptr, nullptr, &si, &pi))
{
MERROR("CreateProcess failed. Error code " << GetLastError());
oxen::log::error(logcat, "CreateProcess failed. Error code {}", GetLastError());
return -1;
}
@ -100,18 +100,18 @@ int spawn(const fs::path& filename, const std::vector<std::string>& args, bool w
DWORD result = WaitForSingleObject(pi.hProcess, INFINITE);
if (result != WAIT_OBJECT_0)
{
MERROR("WaitForSingleObject failed. Result " << result << ", error code " << GetLastError());
oxen::log::error(logcat, "WaitForSingleObject failed. Result {}, error code {}", result, GetLastError());
return -1;
}
DWORD exitCode;
if (!GetExitCodeProcess(pi.hProcess, &exitCode))
{
MERROR("GetExitCodeProcess failed. Error code " << GetLastError());
oxen::log::error(logcat, "GetExitCodeProcess failed. Error code {}", GetLastError());
return -1;
}
MINFO("Child exited with " << exitCode);
oxen::log::info(logcat, "Child exited with {}", exitCode);
return static_cast<int>(exitCode);
#else
std::vector<char*> argv(args.size() + 1);
@ -122,7 +122,7 @@ int spawn(const fs::path& filename, const std::vector<std::string>& args, bool w
pid_t pid = fork();
if (pid < 0)
{
MERROR("Error forking: " << strerror(errno));
oxen::log::error(logcat, "Error forking: {}", strerror(errno));
return -1;
}
@ -133,7 +133,7 @@ int spawn(const fs::path& filename, const std::vector<std::string>& args, bool w
close(0);
char *envp[] = {NULL};
execve(filename.c_str(), argv.data(), envp);
MERROR("Failed to execve: " << strerror(errno));
oxen::log::error(logcat, "Failed to execve: {}", strerror(errno));
return -1;
}
@ -151,22 +151,22 @@ int spawn(const fs::path& filename, const std::vector<std::string>& args, bool w
int wstatus = 0;
pid_t w = waitpid(pid, &wstatus, WUNTRACED | WCONTINUED);
if (w < 0) {
MERROR("Error waiting for child: " << strerror(errno));
oxen::log::error(logcat, "Error waiting for child: {}", strerror(errno));
return -1;
}
if (WIFEXITED(wstatus))
{
MINFO("Child exited with " << WEXITSTATUS(wstatus));
oxen::log::info(logcat, "Child exited with {}", WEXITSTATUS(wstatus));
return WEXITSTATUS(wstatus);
}
if (WIFSIGNALED(wstatus))
{
MINFO("Child killed by " << WEXITSTATUS(wstatus));
oxen::log::info(logcat, "Child killed by {}", WEXITSTATUS(wstatus));
return WEXITSTATUS(wstatus);
}
}
}
MERROR("Secret passage found");
oxen::log::error(logcat, "Secret passage found");
return -1;
#endif
}

View File

@ -26,6 +26,7 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "epee/misc_log_ex.h"
#include "logging/oxen_logger.h"
#include "common/threadpool.h"
#include "cryptonote_config.h"
@ -36,6 +37,8 @@ static thread_local bool is_leaf = false;
namespace tools
{
static auto logcat = oxen::log::Cat("global");
threadpool::threadpool(unsigned int max_threads) : running(true), active(0) {
create(max_threads);
}
@ -112,7 +115,7 @@ threadpool::waiter::~waiter()
{
std::unique_lock lock{mt};
if (num)
MERROR("wait should have been called before waiter dtor - waiting now");
oxen::log::error(logcat, "wait should have been called before waiter dtor - waiting now");
}
catch (...) { /* ignore */ }
try

View File

@ -33,6 +33,7 @@
#include <string>
#include <iomanip>
#include <thread>
#include <fmt/color.h>
#include <date/date.h>
@ -42,6 +43,7 @@
#include "util.h"
#include "epee/readline_buffer.h"
#include "epee/misc_log_ex.h"
#include "logging/oxen_logger.h"
#include "string_util.h"
#include "i18n.h"
@ -51,11 +53,9 @@
#include <gnu/libc-version.h>
#endif
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "util"
namespace tools
{
static auto logcat = oxen::log::Cat("util");
bool disable_core_dumps()
{
@ -65,7 +65,7 @@ namespace tools
rlimit.rlim_cur = rlimit.rlim_max = 0;
if (setrlimit(RLIMIT_CORE, &rlimit))
{
MWARNING("Failed to disable core dumps");
oxen::log::warning(logcat, "Failed to disable core dumps");
return false;
}
#endif
@ -78,7 +78,7 @@ namespace tools
struct rlimit rlim;
if (getrlimit(RLIMIT_MEMLOCK, &rlim) < 0)
{
MERROR("Failed to determine the lockable memory limit");
oxen::log::error(logcat, "Failed to determine the lockable memory limit");
return -1;
}
return rlim.rlim_cur;
@ -89,12 +89,10 @@ namespace tools
bool on_startup()
{
mlog_configure("", true);
#ifdef __GLIBC__
const char *ver = ::gnu_get_libc_version();
if (!strcmp(ver, "2.25"))
MCLOG_RED(el::Level::Warning, "global", "Running with glibc " << ver << ", hangs may occur - change glibc version if possible");
oxen::log::warning(logcat, fmt::format(fg(fmt::terminal_color::red), "Running with glibc {}, hangs may occur - change glibc version if possible", ver));
#endif
return true;
@ -164,7 +162,7 @@ namespace tools
}
else
{
return {};
return std::nullopt;
}
}

View File

@ -66,6 +66,7 @@ target_link_libraries(cncrypto
Boost::thread
sodium
PRIVATE
logging
extra)
if (CMAKE_CXX_COMPILER_ID MATCHES Clang OR CMAKE_CXX_COMPILER_ID STREQUAL GNU)

69
src/crypto/fmt.h Normal file
View File

@ -0,0 +1,69 @@
#pragma once
#include <fmt/format.h>
#include "crypto.h"
#include "hash.h"
template <>
struct fmt::formatter<crypto::public_key> : fmt::formatter<std::string> {
auto format(crypto::public_key v, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("<{}>", tools::type_to_hex(v)), ctx);
}
};
template <>
struct fmt::formatter<crypto::secret_key> : fmt::formatter<std::string> {
auto format(crypto::secret_key v, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("<{}>", tools::type_to_hex(v)), ctx);
}
};
template <>
struct fmt::formatter<crypto::key_derivation> : fmt::formatter<std::string> {
auto format(crypto::key_derivation v, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("<{}>", tools::type_to_hex(v)), ctx);
}
};
template <>
struct fmt::formatter<crypto::key_image> : fmt::formatter<std::string> {
auto format(crypto::key_image v, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("<{}>", tools::type_to_hex(v)), ctx);
}
};
template <>
struct fmt::formatter<crypto::signature> : fmt::formatter<std::string> {
auto format(crypto::signature v, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("<{}>", tools::type_to_hex(v)), ctx);
}
};
template <>
struct fmt::formatter<crypto::ed25519_public_key> : fmt::formatter<std::string> {
auto format(crypto::ed25519_public_key v, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("<{}>", tools::type_to_hex(v)), ctx);
}
};
template <>
struct fmt::formatter<crypto::x25519_public_key> : fmt::formatter<std::string> {
auto format(crypto::x25519_public_key v, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("<{}>", tools::type_to_hex(v)), ctx);
}
};
template <>
struct fmt::formatter<crypto::hash> : fmt::formatter<std::string> {
auto format(crypto::hash h, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("<{}>", tools::type_to_hex(h)), ctx);
}
};
template <>
struct fmt::formatter<crypto::hash8> : fmt::formatter<std::string> {
auto format(crypto::hash8 h, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("<{}>", tools::type_to_hex(h)), ctx);
}
};

View File

@ -37,7 +37,6 @@
#include "randomx.h"
#include "c_threads.h"
#include "hash-ops.h"
#include "epee/misc_log_ex.h"
#define RX_LOGCAT "randomx"
@ -223,7 +222,6 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
if (cache == NULL) {
cache = randomx_alloc_cache(flags | RANDOMX_FLAG_LARGE_PAGES);
if (cache == NULL) {
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX cache");
cache = randomx_alloc_cache(flags);
}
if (cache == NULL)
@ -249,7 +247,6 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
if (rx_dataset == NULL) {
rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_LARGE_PAGES);
if (rx_dataset == NULL) {
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX dataset");
rx_dataset = randomx_alloc_dataset(RANDOMX_FLAG_DEFAULT);
}
if (rx_dataset != NULL)
@ -262,14 +259,12 @@ void rx_slow_hash(const uint64_t mainheight, const uint64_t seedheight, const ch
miners = 0;
if (!rx_dataset_nomem) {
rx_dataset_nomem = 1;
mwarning(RX_LOGCAT, "Couldn't allocate RandomX dataset for miner");
}
}
CTHR_MUTEX_UNLOCK(rx_dataset_mutex);
}
rx_vm = randomx_create_vm(flags | RANDOMX_FLAG_LARGE_PAGES, rx_sp->rs_cache, rx_dataset);
if(rx_vm == NULL) { //large pages failed
mdebug(RX_LOGCAT, "Couldn't use largePages for RandomX VM");
rx_vm = randomx_create_vm(flags, rx_sp->rs_cache, rx_dataset);
}
if(rx_vm == NULL) {//fallback if everything fails

View File

@ -44,4 +44,5 @@ target_link_libraries(cryptonote_basic
Boost::program_options
Boost::serialization
filesystem
logging
extra)

View File

@ -43,15 +43,13 @@ extern "C"
#include "cryptonote_config.h"
#include "common/meta.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "account"
using namespace std;
DISABLE_VS_WARNINGS(4244 4345)
namespace cryptonote
{
static auto logcat = oxen::log::Cat("account");
//-----------------------------------------------------------------
hw::device& account_keys::get_device() const {
@ -60,7 +58,7 @@ DISABLE_VS_WARNINGS(4244 4345)
//-----------------------------------------------------------------
void account_keys::set_device( hw::device &hwdev) {
m_device = &hwdev;
MCDEBUG("device", "account_keys::set_device device type: " << tools::type_name(typeid(hwdev)));
oxen::log::debug(oxen::log::Cat("device"), "account_keys::set_device device type: {}", tools::type_name(typeid(hwdev)));
}
//-----------------------------------------------------------------
static void derive_key(const crypto::chacha_key &base_key, crypto::chacha_key &key)
@ -143,7 +141,7 @@ DISABLE_VS_WARNINGS(4244 4345)
try{
m_keys.get_device().disconnect();
} catch (const std::exception &e){
MERROR("Device disconnect exception: " << e.what());
oxen::log::error(logcat, "Device disconnect exception: {}", e.what());
}
}
//-----------------------------------------------------------------
@ -207,7 +205,7 @@ DISABLE_VS_WARNINGS(4244 4345)
void account_base::create_from_device(hw::device &hwdev)
{
m_keys.set_device(hwdev);
MCDEBUG("device", "device type: " << tools::type_name(typeid(hwdev)));
oxen::log::debug(oxen::log::Cat("device"), "device type: {}", tools::type_name(typeid(hwdev)));
CHECK_AND_ASSERT_THROW_MES(hwdev.init(), "Device init failed");
CHECK_AND_ASSERT_THROW_MES(hwdev.connect(), "Device connect failed");
try {

View File

@ -35,6 +35,7 @@
#include "epee/net/net_utils_base.h"
#include "epee/copyable_atomic.h"
#include "crypto/hash.h"
#include "fmt/format.h"
using namespace std::literals;
@ -92,3 +93,11 @@ namespace cryptonote
}
}
template <typename T>
struct fmt::formatter<T, char, std::enable_if_t<std::is_base_of_v<epee::net_utils::connection_context_base, T>>> : fmt::formatter<std::string> {
auto format(epee::net_utils::connection_context_base connection_context, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("[{}]", epee::net_utils::print_connection_context_short(connection_context)), ctx);
}
};

View File

@ -45,6 +45,8 @@
#include "ringct/rctTypes.h"
#include "device/device.hpp"
#include "txtypes.h"
#include "logging/oxen_logger.h"
#include <fmt/format.h>
namespace service_nodes
{
@ -226,7 +228,7 @@ namespace cryptonote
{
if (out_index >= output_unlock_times.size())
{
LOG_ERROR("Tried to get unlock time of a v3 transaction with missing output unlock time");
oxen::log::error(globallogcat, "Tried to get unlock time of a v3 transaction with missing output unlock time");
return unlock_time;
}
return output_unlock_times[out_index];
@ -603,6 +605,21 @@ namespace cryptonote
}
}
template <>
struct fmt::formatter<cryptonote::txtype> : fmt::formatter<std::string> {
auto format(cryptonote::txtype t, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("{}", cryptonote::transaction::type_to_string(t)), ctx);
}
};
template <>
struct fmt::formatter<cryptonote::txversion> : fmt::formatter<std::string> {
auto format(cryptonote::txversion v, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("{}", cryptonote::transaction::version_to_string(v)), ctx);
}
};
namespace std {
template <>
struct hash<cryptonote::account_public_address>

View File

@ -39,13 +39,13 @@
#include "crypto/hash.h"
#include "epee/int-util.h"
#include "common/oxen.h"
#include "logging/oxen_logger.h"
#include <cfenv>
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "cn"
namespace cryptonote {
static auto logcat = oxen::log::Cat("cn");
struct integrated_address {
account_public_address adr;
crypto::hash8 payment_id;
@ -133,7 +133,7 @@ namespace cryptonote {
}
if(current_block_weight > 2 * median_weight) {
MERROR("Block cumulative weight is too big: " << current_block_weight << ", expected less than " << 2 * median_weight);
oxen::log::error(logcat, "Block cumulative weight is too big: {}, expected less than {}", current_block_weight, 2 * median_weight);
return false;
}
@ -225,7 +225,7 @@ namespace cryptonote {
uint64_t prefix{0};
if (!tools::base58::decode_addr(str, prefix, data))
{
LOG_PRINT_L2("Invalid address format");
oxen::log::debug(logcat, "Invalid address format");
return false;
}
@ -245,9 +245,7 @@ namespace cryptonote {
info.has_payment_id = false;
}
else {
LOG_PRINT_L1("Wrong address prefix: " << prefix << ", expected " << address_prefix
<< " or " << integrated_address_prefix
<< " or " << subaddress_prefix);
oxen::log::info(logcat, "Wrong address prefix: {}, expected {} or {} or {}", prefix, address_prefix, integrated_address_prefix, subaddress_prefix);
return false;
}
@ -264,13 +262,13 @@ namespace cryptonote {
serialization::parse_binary(data, info.address);
}
} catch (const std::exception& e) {
LOG_PRINT_L1("Account public address keys can't be parsed: "s + e.what());
oxen::log::info(logcat, "Account public address keys can't be parsed: "s + e.what());
return false;
}
if (!crypto::check_key(info.address.m_spend_public_key) || !crypto::check_key(info.address.m_view_public_key))
{
LOG_PRINT_L1("Failed to validate address keys");
oxen::log::info(logcat, "Failed to validate address keys");
return false;
}

View File

@ -46,20 +46,21 @@
#include "cryptonote_config.h"
#include "crypto/crypto.h"
#include "crypto/hash.h"
#include "crypto/fmt.h"
#include "ringct/rctSigs.h"
#include "cryptonote_basic/verification_context.h"
#include "cryptonote_core/service_node_voting.h"
#include "cryptonote_core/oxen_name_system.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "cn"
#include <fmt/std.h>
using namespace crypto;
#define CHECK_AND_ASSERT_THROW_MES_L1(expr, message) {if(!(expr)) {MWARNING(message); throw std::runtime_error(message);}}
#define CHECK_AND_ASSERT_THROW_MES_L1(expr, message) {if(!(expr)) {oxen::log::warning(logcat, message); throw std::runtime_error(message);}}
namespace cryptonote
{
static auto logcat = oxen::log::Cat("cn");
static inline unsigned char *operator &(ec_point &point) {
return &reinterpret_cast<unsigned char &>(point);
}
@ -134,14 +135,14 @@ namespace cryptonote
return true;
if (rv.outPk.size() != tx.vout.size())
{
LOG_PRINT_L1("Failed to parse transaction from blob, bad outPk size in tx " << get_transaction_hash(tx));
oxen::log::info(logcat, "Failed to parse transaction from blob, bad outPk size in tx {}", get_transaction_hash(tx));
return false;
}
for (size_t n = 0; n < tx.rct_signatures.outPk.size(); ++n)
{
if (!std::holds_alternative<txout_to_key>(tx.vout[n].target))
{
LOG_PRINT_L1("Unsupported output type in tx " << get_transaction_hash(tx));
oxen::log::info(logcat, "Unsupported output type in tx {}", get_transaction_hash(tx));
return false;
}
rv.outPk[n].dest = rct::pk2rct(var::get<txout_to_key>(tx.vout[n].target).key);
@ -154,18 +155,18 @@ namespace cryptonote
{
if (rv.p.bulletproofs.size() != 1)
{
LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs size in tx " << get_transaction_hash(tx));
oxen::log::info(logcat, "Failed to parse transaction from blob, bad bulletproofs size in tx {}", get_transaction_hash(tx));
return false;
}
if (rv.p.bulletproofs[0].L.size() < 6)
{
LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs L size in tx " << get_transaction_hash(tx));
oxen::log::info(logcat, "Failed to parse transaction from blob, bad bulletproofs L size in tx {}", get_transaction_hash(tx));
return false;
}
const size_t max_outputs = 1 << (rv.p.bulletproofs[0].L.size() - 6);
if (max_outputs < tx.vout.size())
{
LOG_PRINT_L1("Failed to parse transaction from blob, bad bulletproofs max outputs in tx " << get_transaction_hash(tx));
oxen::log::info(logcat, "Failed to parse transaction from blob, bad bulletproofs max outputs in tx {}", get_transaction_hash(tx));
return false;
}
const size_t n_amounts = tx.vout.size();
@ -196,7 +197,7 @@ namespace cryptonote
try {
serialization::serialize(ba, tx);
} catch (const std::exception& e) {
LOG_ERROR("Failed to parse and validate transaction from blob: " << e.what());
oxen::log::error(logcat, "Failed to parse and validate transaction from blob: {}", e.what());
return false;
}
CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data");
@ -211,7 +212,7 @@ namespace cryptonote
try {
tx.serialize_base(ba);
} catch (const std::exception& e) {
LOG_ERROR("Failed to parse transaction base from blob: " << e.what());
oxen::log::error(logcat, "Failed to parse transaction base from blob: {}", e.what());
return false;
}
CHECK_AND_ASSERT_MES(expand_transaction_1(tx, true), false, "Failed to expand transaction data");
@ -225,7 +226,7 @@ namespace cryptonote
try {
serialization::value(ba, tx);
} catch (const std::exception& e) {
LOG_ERROR("Failed to parse transaction prefix from blob: " << e.what());
oxen::log::error(logcat, "Failed to parse transaction prefix from blob: {}", e.what());
return false;
}
return true;
@ -237,7 +238,7 @@ namespace cryptonote
try {
serialization::serialize(ba, tx);
} catch (const std::exception& e) {
LOG_ERROR("Failed to parse and validate transaction from blob + hash: " << e.what());
oxen::log::error(logcat, "Failed to parse and validate transaction from blob + hash: {}", e.what());
return false;
}
CHECK_AND_ASSERT_MES(expand_transaction_1(tx, false), false, "Failed to expand transaction data");
@ -269,7 +270,7 @@ namespace cryptonote
bool r = hwdev.generate_key_derivation(tx_public_key, ack.m_view_secret_key, recv_derivation);
if (!r)
{
MWARNING("key image helper: failed to generate_key_derivation(" << tx_public_key << ", " << ack.m_view_secret_key << ")");
oxen::log::warning(logcat, "key image helper: failed to generate_key_derivation({}, {})", tx_public_key, ack.m_view_secret_key);
memcpy(&recv_derivation, rct::identity().bytes, sizeof(recv_derivation));
}
@ -280,7 +281,7 @@ namespace cryptonote
r = hwdev.generate_key_derivation(additional_tx_public_keys[i], ack.m_view_secret_key, additional_recv_derivation);
if (!r)
{
MWARNING("key image helper: failed to generate_key_derivation(" << additional_tx_public_keys[i] << ", " << ack.m_view_secret_key << ")");
oxen::log::warning(logcat, "key image helper: failed to generate_key_derivation({}, {})", additional_tx_public_keys[i], ack.m_view_secret_key);
}
else
{
@ -527,7 +528,7 @@ namespace cryptonote
try {
serialization::deserialize_all(ar, tx_extra_fields);
} catch (const std::exception& e) {
MWARNING(__func__ << ": failed to deserialize extra field: " << e.what() << "; extra = " << oxenc::to_hex(tx_extra.begin(), tx_extra.end()));
oxen::log::warning(logcat, "{}: failed to deserialize extra field: {}; extra = {}", __func__, e.what(), oxenc::to_hex(tx_extra.begin(), tx_extra.end()));
return false;
}
@ -548,7 +549,7 @@ namespace cryptonote
for (auto& f : tx_extra_fields)
serialization::value(ar, f);
} catch (const std::exception& e) {
LOG_PRINT_L1("failed to serialize tx extra field: " << e.what());
oxen::log::info(logcat, "failed to serialize tx extra field: {}", e.what());
return false;
}
@ -608,8 +609,11 @@ namespace cryptonote
bool add_additional_tx_pub_keys_to_extra(std::vector<uint8_t>& tx_extra, const std::vector<crypto::public_key>& additional_pub_keys)
{
tx_extra_field field = tx_extra_additional_pub_keys{ additional_pub_keys };
bool r = add_tx_extra_field_to_tx_extra(tx_extra, field);
CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to serialize tx extra additional tx pub keys");
if (!add_tx_extra_field_to_tx_extra(tx_extra, field))
{
oxen::log::info(logcat, "failed to serialize tx extra additional tx pub keys");
return false;
}
return true;
}
//---------------------------------------------------------------
@ -678,17 +682,24 @@ namespace cryptonote
bool add_tx_key_image_proofs_to_tx_extra(std::vector<uint8_t>& tx_extra, const tx_extra_tx_key_image_proofs& proofs)
{
tx_extra_field field = proofs;
bool result = add_tx_extra_field_to_tx_extra(tx_extra, field);
CHECK_AND_NO_ASSERT_MES_L1(result, false, "failed to serialize tx extra tx key image proof");
return result;
if (!add_tx_extra_field_to_tx_extra(tx_extra, field))
{
oxen::log::info(logcat, "failed to serialize tx extra tx key image proof");
return false;
}
return true;
}
//---------------------------------------------------------------
bool add_tx_key_image_unlock_to_tx_extra(std::vector<uint8_t>& tx_extra, const tx_extra_tx_key_image_unlock& unlock)
{
tx_extra_field field = unlock;
bool result = add_tx_extra_field_to_tx_extra(tx_extra, field);
CHECK_AND_NO_ASSERT_MES_L1(result, false, "failed to serialize tx extra tx key image unlock");
return result;
if (!add_tx_extra_field_to_tx_extra(tx_extra, field))
{
oxen::log::info(logcat, "failed to serialize tx extra tx key image unlock");
return false;
}
return true;
}
//---------------------------------------------------------------
bool get_service_node_contributor_from_tx_extra(const std::vector<uint8_t>& tx_extra, cryptonote::account_public_address& address)
@ -718,8 +729,12 @@ namespace cryptonote
txreg.hf_or_expiration = reg.hf;
txreg.signature = reg.signature;
bool r = add_tx_extra_field_to_tx_extra(tx_extra, field);
CHECK_AND_NO_ASSERT_MES_L1(r, false, "failed to serialize tx extra registration tx");
if (!add_tx_extra_field_to_tx_extra(tx_extra, field))
{
oxen::log::info(logcat, "failed to serialize tx extra registration tx");
return false;
}
return true;
}
//---------------------------------------------------------------
@ -779,7 +794,7 @@ namespace cryptonote
value(newar, field);
} while (ar.remaining_bytes() > 0);
} catch (const std::exception& e) {
LOG_PRINT_L1(__func__ << ": failed to deserialize extra field: " << e.what() << "; extra = " << oxenc::to_hex(tx_extra.begin(), tx_extra.end()));
oxen::log::info(logcat, "{}: failed to deserialize extra field: {}; extra = {}", __func__, e.what(), oxenc::to_hex(tx_extra.begin(), tx_extra.end()));
return false;
}
@ -837,9 +852,12 @@ namespace cryptonote
bool add_burned_amount_to_tx_extra(std::vector<uint8_t>& tx_extra, uint64_t burn)
{
tx_extra_field field = tx_extra_burn{burn};
bool result = add_tx_extra_field_to_tx_extra(tx_extra, field);
CHECK_AND_NO_ASSERT_MES_L1(result, false, "failed to serialize tx extra burn amount");
return result;
if (!add_tx_extra_field_to_tx_extra(tx_extra, field))
{
oxen::log::info(logcat, "failed to serialize tx extra burn amount");
return false;
}
return true;
}
//---------------------------------------------------------------
bool get_inputs_money_amount(const transaction& tx, uint64_t& money)
@ -883,14 +901,17 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
bool check_outs_valid(const transaction& tx)
{
if (!tx.is_transfer())
if (!tx.is_transfer() && tx.vout.size() != 0)
{
CHECK_AND_NO_ASSERT_MES(tx.vout.size() == 0, false, "tx type: " << tx.type << " must have 0 outputs, received: " << tx.vout.size() << ", id=" << get_transaction_hash(tx));
oxen::log::warning(logcat, "tx type: {} must have 0 outputs, received: {}, id={}", transaction::type_to_string(tx.type), tx.vout.size(), get_transaction_hash(tx));
return false;
}
if (tx.version >= txversion::v3_per_output_unlock_times)
if (tx.version >= txversion::v3_per_output_unlock_times && tx.vout.size() != tx.output_unlock_times.size())
{
CHECK_AND_NO_ASSERT_MES(tx.vout.size() == tx.output_unlock_times.size(), false, "tx version: " << tx.version << "must have equal number of output unlock times and outputs");
oxen::log::warning(logcat, "tx version: {} must have equal number of output unlock times and outputs", transaction::version_to_string(tx.version));
return false;
}
for(const tx_out& out: tx.vout)
@ -901,7 +922,11 @@ namespace cryptonote
if (tx.version == txversion::v1)
{
CHECK_AND_NO_ASSERT_MES(0 < out.amount, false, "zero amount output in transaction id=" << get_transaction_hash(tx));
if (out.amount <= 0)
{
oxen::log::warning(logcat, "zero amount output in transaction id={}", get_transaction_hash(tx));
return false;
}
}
if(!check_key(var::get<txout_to_key>(out.target).key))
@ -1202,7 +1227,7 @@ namespace cryptonote
const_cast<transaction&>(t).rct_signatures.p.serialize_rctsig_prunable(
ba, t.rct_signatures.type, t.vin.size(), t.vout.size(), mixin);
} catch (const std::exception& e) {
LOG_ERROR("Failed to serialize rct signatures (prunable): " << e.what());
oxen::log::error(logcat, "Failed to serialize rct signatures (prunable): {}", e.what());
return false;
}
cryptonote::get_blob_hash(ba.str(), res);
@ -1289,7 +1314,7 @@ namespace cryptonote
try {
tt.rct_signatures.serialize_rctsig_base(ba, t.vin.size(), t.vout.size());
} catch (const std::exception& e) {
LOG_ERROR("Failed to serialize rct signatures base: " << e.what());
oxen::log::error(logcat, "Failed to serialize rct signatures base: {}", e.what());
return false;
}
cryptonote::get_blob_hash(ba.str(), hashes[1]);
@ -1302,7 +1327,7 @@ namespace cryptonote
}
else if (!calculate_transaction_prunable_hash(t, &blob, hashes[2]))
{
LOG_ERROR("Failed to get tx prunable hash");
oxen::log::error(logcat, "Failed to get tx prunable hash");
return false;
}
@ -1422,7 +1447,7 @@ namespace cryptonote
try {
serialization::serialize(ba, b);
} catch (const std::exception& e) {
LOG_ERROR("Failed to parse block from blob: " << e.what());
oxen::log::error(logcat, "Failed to parse block from blob: {}", e.what());
return false;
}
b.invalidate_hashes();

View File

@ -38,6 +38,7 @@
#include "common/meta.h"
#include "common/string_util.h"
#include "serialization/binary_utils.h"
#include "logging/oxen_logger.h"
#include <unordered_map>
namespace epee
@ -272,7 +273,7 @@ namespace cryptonote
blob = serialization::dump_binary(const_cast<std::remove_const_t<T>&>(val));
return true;
} catch (const std::exception& e) {
LOG_ERROR("Serialization of " << tools::type_name(typeid(T)) << " failed: " << e.what());
oxen::log::error(globallogcat, "Serialization of {} failed: {}", tools::type_name(typeid(T)), e.what());
return false;
}
}
@ -317,7 +318,7 @@ namespace cryptonote
try {
serialize(ar, obj);
} catch (const std::exception& e) {
LOG_ERROR("obj_to_json_str failed: serialization failed: " << e.what());
oxen::log::error(globallogcat, "obj_to_json_str failed: serialization failed: {}", e.what());
return ""s;
}
return ss.str();

View File

@ -39,9 +39,9 @@
#include "common/string_util.h"
#include "epee/string_tools.h"
#include "epee/storages/portable_storage_template_helper.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "miner"
#include <logging/oxen_logger.h>
#include <fmt/std.h>
#include <fmt/color.h>
#define AUTODETECT_WINDOW 10 // seconds
#define AUTODETECT_GAIN_THRESHOLD 1.02f // 2%
@ -53,6 +53,7 @@ extern "C" void rx_slow_hash_free_state();
namespace cryptonote
{
static auto logcat = oxen::log::Cat("miner");
namespace
{
@ -102,7 +103,7 @@ namespace cryptonote
if(!m_phandler->create_next_miner_block_template(bl, m_mine_address, di, height, expected_reward, ""s))
{
LOG_ERROR("Failed to get_block_template(), stopping mining");
oxen::log::error(logcat, "Failed to get_block_template(), stopping mining");
return false;
}
set_block_template(bl, di, height, expected_reward);
@ -147,7 +148,7 @@ namespace cryptonote
address_parse_info info;
if(!cryptonote::get_account_address_from_str(info, nettype, command_line::get_arg(vm, arg_start_mining)) || info.is_subaddress)
{
LOG_ERROR("Target account address " << command_line::get_arg(vm, arg_start_mining) << " has wrong format, starting daemon canceled");
oxen::log::error(logcat, "Target account address {} has wrong format, starting daemon canceled", command_line::get_arg(vm, arg_start_mining));
return false;
}
m_mine_address = info.address;
@ -184,13 +185,13 @@ namespace cryptonote
std::unique_lock lock{m_threads_lock};
if(is_mining())
{
LOG_ERROR("Starting miner but it's already started");
oxen::log::error(logcat, "Starting miner but it's already started");
return false;
}
if(!m_threads.empty())
{
LOG_ERROR("Unable to start miner because there are active mining threads");
oxen::log::error(logcat, "Unable to start miner because there are active mining threads");
return false;
}
@ -199,12 +200,12 @@ namespace cryptonote
m_stop = false;
m_stop_height = stop_after > 0 ? m_height + stop_after : std::numeric_limits<uint64_t>::max();
if (stop_after > 0)
MGINFO("Mining until height " << m_stop_height);
oxen::log::info(logcat, "Mining until height {}", m_stop_height);
for (int i = 0; i < m_threads_total; i++)
m_threads.emplace_back([=] { return worker_thread(i, slow_mining); });
MINFO("Mining has started with " << m_threads_total << " threads, good luck!" );
oxen::log::info(logcat, "Mining has started with {} threads, good luck!", m_threads_total);
return true;
}
@ -222,13 +223,13 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------------
bool miner::stop()
{
MTRACE("Miner has received stop signal");
oxen::log::trace(logcat, "Miner has received stop signal");
std::unique_lock lock{m_threads_lock};
bool mining = !m_threads.empty();
if (!mining)
{
MTRACE("Not mining - nothing to stop" );
oxen::log::trace(logcat, "Not mining - nothing to stop" );
return true;
}
@ -237,7 +238,7 @@ namespace cryptonote
if (th.joinable())
th.join();
MINFO("Mining has been stopped, " << m_threads.size() << " finished" );
oxen::log::info(logcat, "Mining has been stopped, {} finished", m_threads.size());
m_threads.clear();
rx_stop_mining();
return true;
@ -271,30 +272,29 @@ namespace cryptonote
void miner::pause()
{
std::unique_lock lock{m_miners_count_mutex};
MDEBUG("miner::pause: " << m_pausers_count << " -> " << (m_pausers_count + 1));
oxen::log::debug(logcat, "miner::pause: {} -> {}", m_pausers_count, (m_pausers_count + 1));
++m_pausers_count;
if(m_pausers_count == 1 && is_mining())
MDEBUG("MINING PAUSED");
oxen::log::debug(logcat, "MINING PAUSED");
}
//-----------------------------------------------------------------------------------------------------
void miner::resume()
{
std::unique_lock lock{m_miners_count_mutex};
MDEBUG("miner::resume: " << m_pausers_count << " -> " << (m_pausers_count - 1));
oxen::log::debug(logcat, "miner::resume: {} -> {}", m_pausers_count, (m_pausers_count - 1));
--m_pausers_count;
if(m_pausers_count < 0)
{
m_pausers_count = 0;
MERROR("Unexpected miner::resume() called");
oxen::log::error(logcat, "Unexpected miner::resume() called");
}
if(!m_pausers_count && is_mining())
MDEBUG("MINING RESUMED");
oxen::log::debug(logcat, "MINING RESUMED");
}
//-----------------------------------------------------------------------------------------------------
bool miner::worker_thread(uint32_t index, bool slow_mining)
{
MLOG_SET_THREAD_NAME(std::string("[miner ") + std::to_string(index) + "]");
MGINFO("Miner thread was started ["<< index << "]");
oxen::log::info(logcat, "Miner thread was started [{}]", index);
uint32_t nonce = m_starter_nonce + index;
uint64_t height = 0;
difficulty_type local_diff = 0;
@ -325,7 +325,7 @@ namespace cryptonote
if(!local_template_ver)//no any set_block_template call
{
LOG_PRINT_L2("Block template not set yet");
oxen::log::debug(logcat, "Block template not set yet");
std::this_thread::sleep_for(1s);
continue;
}
@ -345,7 +345,7 @@ namespace cryptonote
if(check_hash(h, local_diff))
{
//we lucky!
MGINFO_GREEN("Found block " << get_block_hash(b) << " at height " << height << " for difficulty: " << local_diff);
oxen::log::info(logcat, fmt::format(fg(fmt::terminal_color::green), "Found block {} at height {} for difficulty: {}", get_block_hash(b), height, local_diff));
cryptonote::block_verification_context bvc;
m_phandler->handle_block_found(b, bvc);
}
@ -354,7 +354,7 @@ namespace cryptonote
++m_hashes;
}
rx_slow_hash_free_state();
MGINFO("Miner thread stopped ["<< index << "]");
oxen::log::info(logcat, "Miner thread stopped [{}]", index);
if (call_stop)
// Call in a detached thread because the thread calling stop() needs to be able to join this
// worker thread.

View File

@ -58,6 +58,7 @@ target_link_libraries(cryptonote_core
Boost::program_options
SQLiteCpp
systemd
logging
extra)
if(PER_BLOCK_CHECKPOINT)

File diff suppressed because it is too large Load Diff

View File

@ -70,14 +70,13 @@ extern "C" {
#include "epee/memwipe.h"
#include "common/i18n.h"
#include "epee/net/local_ip.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "cn"
#include "logging/oxen_logger.h"
#include <fmt/std.h>
#include <fmt/color.h>
#include <oxenmq/fmt.h>
DISABLE_VS_WARNINGS(4355)
#define MERROR_VER(x) MCERROR("verify", x)
#define BAD_SEMANTICS_TXES_MAX_SIZE 100
// basically at least how many bytes the block itself serializes to without the miner tx
@ -85,6 +84,10 @@ DISABLE_VS_WARNINGS(4355)
namespace cryptonote
{
static auto logcat = oxen::log::Cat("cn");
static auto omqlogcat = oxen::log::Cat("omq");
const command_line::arg_descriptor<bool, false> arg_testnet_on = {
"testnet"
, "Run on testnet. The wallet must be launched with --testnet flag."
@ -380,7 +383,7 @@ namespace cryptonote
bool args_okay = true;
if (m_quorumnet_port == 0) {
MFATAL("Quorumnet port cannot be 0; please specify a valid port to listen on with: '--" << arg_quorumnet_port.name << " <port>'");
oxen::log::error(logcat, "Quorumnet port cannot be 0; please specify a valid port to listen on with: '--{} <port>'", arg_quorumnet_port.name);
args_okay = false;
}
@ -388,28 +391,28 @@ namespace cryptonote
if (pub_ip.size())
{
if (!epee::string_tools::get_ip_int32_from_string(m_sn_public_ip, pub_ip)) {
MFATAL("Unable to parse IPv4 public address from: " << pub_ip);
oxen::log::error(logcat, "Unable to parse IPv4 public address from: {}", pub_ip);
args_okay = false;
}
if (!epee::net_utils::is_ip_public(m_sn_public_ip)) {
if (m_service_node_list.debug_allow_local_ips) {
MWARNING("Address given for public-ip is not public; allowing it because dev-allow-local-ips was specified. This service node WILL NOT WORK ON THE PUBLIC OXEN NETWORK!");
oxen::log::warning(logcat, "Address given for public-ip is not public; allowing it because dev-allow-local-ips was specified. This service node WILL NOT WORK ON THE PUBLIC OXEN NETWORK!");
} else {
MFATAL("Address given for public-ip is not public: " << epee::string_tools::get_ip_string_from_int32(m_sn_public_ip));
oxen::log::error(logcat, "Address given for public-ip is not public: {}", epee::string_tools::get_ip_string_from_int32(m_sn_public_ip));
args_okay = false;
}
}
}
else
{
MFATAL("Please specify an IPv4 public address which the service node & storage server is accessible from with: '--" << arg_public_ip.name << " <ip address>'");
oxen::log::error(logcat, "Please specify an IPv4 public address which the service node & storage server is accessible from with: '--{} <ip address>'", arg_public_ip.name);
args_okay = false;
}
if (!args_okay) {
MFATAL("IMPORTANT: One or more required service node-related configuration settings/options were omitted or invalid; "
<< "please fix them and restart oxend.");
oxen::log::error(logcat,
"IMPORTANT: One or more required service node-related configuration settings/options were omitted or invalid please fix them and restart oxend.");
return false;
}
}
@ -589,14 +592,14 @@ namespace cryptonote
// make sure the data directory exists, and try to lock it
if (std::error_code ec; !fs::is_directory(folder, ec) && !fs::create_directories(folder, ec) && ec)
{
MFATAL("Failed to create directory " + folder.u8string() + (ec ? ": " + ec.message() : ""s));
oxen::log::error(logcat, "Failed to create directory " + folder.u8string() + (ec ? ": " + ec.message() : ""s));
return false;
}
std::unique_ptr<BlockchainDB> db(new_db());
if (!db)
{
LOG_ERROR("Failed to initialize a database");
oxen::log::error(logcat, "Failed to initialize a database");
return false;
}
@ -612,7 +615,7 @@ namespace cryptonote
auto sqliteDB = std::make_shared<cryptonote::BlockchainSQLite>(m_nettype, sqlite_db_file_path);
folder /= db->get_db_name();
MGINFO("Loading blockchain from folder " << folder << " ...");
oxen::log::info(logcat, "Loading blockchain from folder {} ...", folder);
// default to fast:async:1 if overridden
blockchain_db_sync_mode sync_mode = db_defaultsync;
@ -624,7 +627,7 @@ namespace cryptonote
// reset the db by removing the database file before opening it
if (!db->remove_data_file(folder))
{
MFATAL("Failed to remove data file in " << folder);
oxen::log::error(logcat, "Failed to remove data file in {}", folder);
return false;
}
fs::remove(ons_db_file_path);
@ -640,7 +643,7 @@ namespace cryptonote
const bool db_sync_mode_is_default = command_line::is_arg_defaulted(vm, cryptonote::arg_db_sync_mode);
for(const auto &option : options)
MDEBUG("option: " << option);
oxen::log::debug(logcat, "option: {}", option);
// default to fast:async:1
uint64_t DEFAULT_FLAGS = DBF_FAST;
@ -699,7 +702,7 @@ namespace cryptonote
}
else
{
LOG_ERROR("Invalid db sync mode: " << options[2]);
oxen::log::error(logcat, "Invalid db sync mode: {}", options[2]);
return false;
}
}
@ -713,7 +716,7 @@ namespace cryptonote
}
catch (const DB_ERROR& e)
{
LOG_ERROR("Error opening database: " << e.what());
oxen::log::error(logcat, "Error opening database: {}", e.what());
return false;
}
@ -739,7 +742,7 @@ namespace cryptonote
}
catch (const std::exception &e)
{
MERROR("Failed to parse reorg notify spec");
oxen::log::error(logcat, "Failed to parse reorg notify spec");
}
try
@ -753,7 +756,7 @@ namespace cryptonote
}
catch (const std::exception &e)
{
MERROR("Failed to parse block notify spec");
oxen::log::error(logcat, "Failed to parse block rate notify spec");
}
cryptonote::test_options regtest_test_options{};
@ -805,9 +808,9 @@ namespace cryptonote
block_sync_size = command_line::get_arg(vm, arg_block_sync_size);
if (block_sync_size > BLOCKS_SYNCHRONIZING_MAX_COUNT)
MERROR("Error --block-sync-size cannot be greater than " << BLOCKS_SYNCHRONIZING_MAX_COUNT);
oxen::log::error(logcat, "Error --block-sync-size cannot be greater than {}", BLOCKS_SYNCHRONIZING_MAX_COUNT);
MGINFO("Loading checkpoints");
oxen::log::info(logcat, "Loading checkpoints");
CHECK_AND_ASSERT_MES(update_checkpoints_from_json_file(), false, "One or more checkpoints loaded from json conflicted with existing checkpoints.");
r = m_miner.init(vm, m_nettype);
@ -821,7 +824,7 @@ namespace cryptonote
// display a message if the blockchain is not pruned yet
if (!m_blockchain_storage.get_blockchain_pruning_seed())
{
MGINFO("Pruning blockchain...");
oxen::log::info(logcat, "Pruning blockchain...");
CHECK_AND_ASSERT_MES(m_blockchain_storage.prune_blockchain(), false, "Failed to prune blockchain");
}
else
@ -860,7 +863,7 @@ namespace cryptonote
try {
generate_pair(privkey, pubkey);
} catch (const std::exception& e) {
MFATAL("failed to generate keypair " << e.what());
oxen::log::error(logcat, "failed to generate keypair {}", e.what());
return false;
}
@ -939,34 +942,21 @@ namespace cryptonote
}
if (m_service_node) {
MGINFO_YELLOW("Service node public keys:");
MGINFO_YELLOW("- primary: " << tools::type_to_hex(keys.pub));
MGINFO_YELLOW("- ed25519: " << tools::type_to_hex(keys.pub_ed25519));
oxen::log::info(logcat, fmt::format(fg(fmt::terminal_color::yellow), "Service node public keys:"));
oxen::log::info(logcat, fmt::format(fg(fmt::terminal_color::yellow), "- primary: {}", tools::type_to_hex(keys.pub)));
oxen::log::info(logcat, fmt::format(fg(fmt::terminal_color::yellow), "- ed25519: {}", tools::type_to_hex(keys.pub_ed25519)));
// .snode address is the ed25519 pubkey, encoded with base32z and with .snode appended:
MGINFO_YELLOW("- lokinet: " << oxenc::to_base32z(tools::view_guts(keys.pub_ed25519)) << ".snode");
MGINFO_YELLOW("- x25519: " << tools::type_to_hex(keys.pub_x25519));
oxen::log::info(logcat, fmt::format(fg(fmt::terminal_color::yellow), "- lokinet: {}.snode", oxenc::to_base32z(tools::view_guts(keys.pub_ed25519))));
oxen::log::info(logcat, fmt::format(fg(fmt::terminal_color::yellow), "- x25519: {}", tools::type_to_hex(keys.pub_x25519)));
} else {
// Only print the x25519 version because it's the only thing useful for a non-SN (for
// encrypted LMQ RPC connections).
MGINFO_YELLOW("x25519 public key: " << tools::type_to_hex(keys.pub_x25519));
oxen::log::info(logcat, fmt::format(fg(fmt::terminal_color::yellow), "x25519 public key: {}", tools::type_to_hex(keys.pub_x25519)));
}
return true;
}
static constexpr el::Level easylogging_level(oxenmq::LogLevel level) {
using namespace oxenmq;
switch (level) {
case LogLevel::fatal: return el::Level::Fatal;
case LogLevel::error: return el::Level::Error;
case LogLevel::warn: return el::Level::Warning;
case LogLevel::info: return el::Level::Info;
case LogLevel::debug: return el::Level::Debug;
case LogLevel::trace: return el::Level::Trace;
default: return el::Level::Unknown;
}
}
oxenmq::AuthLevel core::omq_check_access(const crypto::x25519_public_key& pubkey) const {
auto it = m_omq_auth.find(pubkey);
if (it != m_omq_auth.end())
@ -995,29 +985,29 @@ namespace cryptonote
if (user_auth >= AuthLevel::basic) {
if (user_auth > auth)
auth = user_auth;
MCINFO("omq", "Incoming " << auth << "-authenticated connection");
oxen::log::info(oxen::log::Cat("omq"), "Incoming {}-authenticated connection", auth);
}
MCINFO("omq", "Incoming [" << auth << "] curve connection from " << ip << "/" << x25519_pubkey);
oxen::log::info(oxen::log::Cat("omq"), "Incoming [{}] curve connection from {}/{}", auth, ip, x25519_pubkey);
}
else {
MCINFO("omq", "Incoming [" << auth << "] plain connection from " << ip);
oxen::log::info(oxen::log::Cat("omq"), "Incoming [{}] plain connection from {}", auth, ip);
}
return auth;
}
void core::init_oxenmq(const boost::program_options::variables_map& vm) {
using namespace oxenmq;
MGINFO("Starting oxenmq");
oxen::log::info(omqlogcat, "Starting oxenmq");
m_omq = std::make_unique<OxenMQ>(
tools::copy_guts(m_service_keys.pub_x25519),
tools::copy_guts(m_service_keys.key_x25519),
m_service_node,
[this](std::string_view x25519_pk) { return m_service_node_list.remote_lookup(x25519_pk); },
[](LogLevel level, const char *file, int line, std::string msg) {
// What a lovely interface (<-- sarcasm)
if (ELPP->vRegistry()->allowed(easylogging_level(level), "omq"))
el::base::Writer(easylogging_level(level), file, line, ELPP_FUNC, el::base::DispatchAction::NormalLog).construct("omq") << msg;
[](LogLevel omqlevel, const char *file, int line, std::string msg) {
auto level = *oxen::logging::parse_level(omqlevel);
if(omqlogcat->should_log(level))
omqlogcat->log({file, line, "omq"}, level, "{}", msg);
},
oxenmq::LogLevel::trace
);
@ -1025,7 +1015,7 @@ namespace cryptonote
// ping.ping: a simple debugging target for pinging the omq listener
m_omq->add_category("ping", Access{AuthLevel::none})
.add_request_command("ping", [](Message& m) {
MCINFO("omq", "Received ping from " << m.conn);
oxen::log::info(oxen::log::Cat("omq"), "Received ping from {}", m.conn);
m.send_reply("pong");
})
;
@ -1037,7 +1027,7 @@ namespace cryptonote
if (listen_ip.empty())
listen_ip = "0.0.0.0";
std::string qnet_listen = "tcp://" + listen_ip + ":" + std::to_string(m_quorumnet_port);
MGINFO("- listening on " << qnet_listen << " (quorumnet)");
oxen::log::info(logcat, "- listening on {} (quorumnet)", qnet_listen);
m_omq->listen_curve(qnet_listen,
[this, public_=command_line::get_arg(vm, arg_omq_quorumnet_public)](std::string_view ip, std::string_view pk, bool) {
return omq_allow(ip, pk, public_ ? AuthLevel::basic : AuthLevel::none);
@ -1116,14 +1106,14 @@ namespace cryptonote
{
if(tx_info.blob->size() > MAX_TX_SIZE)
{
LOG_PRINT_L1("WRONG TRANSACTION BLOB, too big size " << tx_info.blob->size() << ", rejected");
oxen::log::info(logcat, "WRONG TRANSACTION BLOB, too big size {}, rejected", tx_info.blob->size());
tx_info.tvc.m_verifivation_failed = true;
tx_info.tvc.m_too_big = true;
return;
}
else if (tx_info.blob->empty())
{
LOG_PRINT_L1("WRONG TRANSACTION BLOB, blob is empty, rejected");
oxen::log::info(logcat, "WRONG TRANSACTION BLOB, blob is empty, rejected");
tx_info.tvc.m_verifivation_failed = true;
return;
}
@ -1131,7 +1121,7 @@ namespace cryptonote
tx_info.parsed = parse_and_validate_tx_from_blob(*tx_info.blob, tx_info.tx, tx_info.tx_hash);
if(!tx_info.parsed)
{
LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to parse, rejected");
oxen::log::info(logcat, "WRONG TRANSACTION BLOB, Failed to parse, rejected");
tx_info.tvc.m_verifivation_failed = true;
return;
}
@ -1142,7 +1132,7 @@ namespace cryptonote
{
if (bad_semantics_txes[idx].find(tx_info.tx_hash) != bad_semantics_txes[idx].end())
{
LOG_PRINT_L1("Transaction already seen with bad semantics, rejected");
oxen::log::info(logcat, "Transaction already seen with bad semantics, rejected");
tx_info.tvc.m_verifivation_failed = true;
return;
}
@ -1152,7 +1142,7 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
void core::set_semantics_failed(const crypto::hash &tx_hash)
{
LOG_PRINT_L1("WRONG TRANSACTION BLOB, Failed to check tx " << tx_hash << " semantic, rejected");
oxen::log::info(logcat, "WRONG TRANSACTION BLOB, Failed to check tx {} semantic, rejected", tx_hash);
bad_semantics_txes_lock.lock();
bad_semantics_txes[0].insert(tx_hash);
if (bad_semantics_txes[0].size() >= BAD_SEMANTICS_TXES_MAX_SIZE)
@ -1177,7 +1167,7 @@ namespace cryptonote
{
if (kept_by_block && get_blockchain_storage().is_within_compiled_block_hash_area())
{
MTRACE("Skipping semantics check for txs kept by block in embedded hash area");
oxen::log::trace(logcat, "Skipping semantics check for txs kept by block in embedded hash area");
return;
}
@ -1201,7 +1191,7 @@ namespace cryptonote
switch (rv.type) {
case rct::RCTType::Null:
// coinbase should not come here, so we reject for all other types
MERROR_VER("Unexpected Null rctSig type");
oxen::log::error(oxen::log::Cat("verify"), "Unexpected Null rctSig type");
set_semantics_failed(tx_info[n].tx_hash);
tx_info[n].tvc.m_verifivation_failed = true;
tx_info[n].result = false;
@ -1209,7 +1199,7 @@ namespace cryptonote
case rct::RCTType::Simple:
if (!rct::verRctSemanticsSimple(rv))
{
MERROR_VER("rct signature semantics check failed");
oxen::log::error(oxen::log::Cat("verify"), "rct signature semantics check failed");
set_semantics_failed(tx_info[n].tx_hash);
tx_info[n].tvc.m_verifivation_failed = true;
tx_info[n].result = false;
@ -1219,7 +1209,7 @@ namespace cryptonote
case rct::RCTType::Full:
if (!rct::verRct(rv, true))
{
MERROR_VER("rct signature semantics check failed");
oxen::log::error(oxen::log::Cat("verify"), "rct signature semantics check failed");
set_semantics_failed(tx_info[n].tx_hash);
tx_info[n].tvc.m_verifivation_failed = true;
tx_info[n].result = false;
@ -1231,7 +1221,7 @@ namespace cryptonote
case rct::RCTType::CLSAG:
if (!is_canonical_bulletproof_layout(rv.p.bulletproofs))
{
MERROR_VER("Bulletproof does not have canonical form");
oxen::log::error(oxen::log::Cat("verify"), "Bulletproof does not have canonical form");
set_semantics_failed(tx_info[n].tx_hash);
tx_info[n].tvc.m_verifivation_failed = true;
tx_info[n].result = false;
@ -1240,7 +1230,7 @@ namespace cryptonote
rvv.push_back(&rv); // delayed batch verification
break;
default:
MERROR_VER("Unknown rct type: " << (int)rv.type);
oxen::log::error(oxen::log::Cat("verify"), "Unknown rct type: {}", (int)rv.type);
set_semantics_failed(tx_info[n].tx_hash);
tx_info[n].tvc.m_verifivation_failed = true;
tx_info[n].result = false;
@ -1249,7 +1239,7 @@ namespace cryptonote
}
if (!rvv.empty() && !rct::verRctSemanticsSimple(rvv))
{
LOG_PRINT_L1("One transaction among this group has bad semantics, verifying one at a time");
oxen::log::info(logcat, "One transaction among this group has bad semantics, verifying one at a time");
const bool assumed_bad = rvv.size() == 1; // if there's only one tx, it must be the bad one
for (size_t n = 0; n < tx_info.size(); ++n)
{
@ -1284,7 +1274,7 @@ namespace cryptonote
}
catch (const std::exception &e)
{
MERROR_VER("Exception in handle_incoming_tx_pre: " << e.what());
oxen::log::error(oxen::log::Cat("verify"), "Exception in handle_incoming_tx_pre: {}", e.what());
info.tvc.m_verifivation_failed = true;
}
});
@ -1297,12 +1287,12 @@ namespace cryptonote
if(m_mempool.have_tx(info.tx_hash))
{
LOG_PRINT_L2("tx " << info.tx_hash << " already have transaction in tx_pool");
oxen::log::debug(logcat, "tx {} already has a transaction in tx_pool", info.tx_hash);
info.already_have = true;
}
else if(m_blockchain_storage.have_tx(info.tx_hash))
{
LOG_PRINT_L2("tx " << info.tx_hash << " already have transaction in blockchain");
oxen::log::debug(logcat, "tx {} already has a transaction in tx_pool", info.tx_hash);
info.already_have = true;
}
}
@ -1346,15 +1336,15 @@ namespace cryptonote
}
if (m_mempool.add_tx(info.tx, info.tx_hash, *info.blob, weight, info.tvc, *local_opts, version, blink_rollback_height))
{
MDEBUG("tx added: " << info.tx_hash);
oxen::log::debug(logcat, "tx added: {}", info.tx_hash);
}
else
{
ok = false;
if (info.tvc.m_verifivation_failed)
MERROR_VER("Transaction verification failed: " << info.tx_hash);
oxen::log::error(oxen::log::Cat("verify"), "Transaction verification failed: {}", info.tx_hash);
else if (info.tvc.m_verifivation_impossible)
MERROR_VER("Transaction verification impossible: " << info.tx_hash);
oxen::log::error(oxen::log::Cat("verify"), "Transaction verification impossible: {}", info.tx_hash);
}
}
@ -1415,7 +1405,7 @@ namespace cryptonote
}
}
MDEBUG("Want " << want_count << " of " << blinks.size() << " incoming blink signature sets after filtering out immutable txes");
oxen::log::debug(logcat, "Want {} of {} incoming blink signature sets after filtering out immutable txes", want_count, blinks.size());
if (!want_count) return results;
// Step 2: filter out any transactions for which we already have a blink signature
@ -1425,14 +1415,14 @@ namespace cryptonote
{
if (want[i] && m_mempool.has_blink(blinks[i].tx_hash))
{
MDEBUG("Ignoring blink data for " << blinks[i].tx_hash << ": already have blink signatures");
oxen::log::debug(logcat, "Ignoring blink data for {}: already have blink signatures", blinks[i].tx_hash);
want[i] = false; // Already have it, move along
want_count--;
}
}
}
MDEBUG("Want " << want_count << " of " << blinks.size() << " incoming blink signature sets after filtering out existing blink sigs");
oxen::log::debug(logcat, "Want {} of {} incoming blink signature sets after filtering out existing blink sigs", want_count, blinks.size());
if (!want_count) return results;
// Step 3: create new blink_tx objects for txes and add the blink signatures. We can do all of
@ -1458,7 +1448,7 @@ namespace cryptonote
std::any_of(bdata.position.begin(), bdata.position.end(), [](const auto &p) { return p >= service_nodes::BLINK_SUBQUORUM_SIZE; }) || // invalid position
std::any_of(bdata.quorum.begin(), bdata.quorum.end(), [](const auto &qi) { return qi >= tools::enum_count<blink_tx::subquorum>; }) // invalid quorum index
) {
MINFO("Invalid blink tx " << bdata.tx_hash << ": invalid signature data");
oxen::log::info(logcat, "Invalid blink tx {}: invalid signature data", bdata.tx_hash);
continue;
}
@ -1472,7 +1462,7 @@ namespace cryptonote
q = get_quorum(service_nodes::quorum_type::blink, q_height);
if (!q)
{
MINFO("Don't have a quorum for height " << q_height << " (yet?), ignoring this blink");
oxen::log::info(logcat, "Don't have a quorum for height {} (yet?), ignoring this blink", q_height);
no_quorum = true;
break;
}
@ -1493,9 +1483,9 @@ namespace cryptonote
}
if (blink.approved())
{
MINFO("Blink tx " << bdata.tx_hash << " blink signatures approved with " << failures.size() << " signature validation failures");
oxen::log::info(logcat, "Blink tx {} blink signatures approved with {} signature validation failures", bdata.tx_hash, failures.size());
for (auto &f : failures)
MDEBUG("- failure for quorum " << int(bdata.quorum[f.first]) << ", position " << int(bdata.position[f.first]) << ": " << f.second);
oxen::log::debug(logcat, "- failure for quorum {}, position {}: {}", int(bdata.quorum[f.first]), int(bdata.position[f.first]), f.second);
}
else
{
@ -1503,7 +1493,7 @@ namespace cryptonote
os << "Blink validation failed:";
for (auto &f : failures)
os << " [" << int(bdata.quorum[f.first]) << ":" << int(bdata.position[f.first]) << "]: " << f.second;
MINFO("Invalid blink tx " << bdata.tx_hash << ": " << os.str());
oxen::log::info(logcat, "Invalid blink tx {}: {}", bdata.tx_hash, os.str());
}
}
@ -1525,7 +1515,7 @@ namespace cryptonote
if (added)
{
MINFO("Added blink signatures for " << added << " blinks");
oxen::log::info(logcat, "Added blink signatures for {} blinks", added);
long_poll_trigger(m_mempool);
}
@ -1544,7 +1534,7 @@ namespace cryptonote
{
if (tx.vin.empty())
{
MERROR_VER("tx with empty inputs, rejected for tx id= " << get_transaction_hash(tx));
oxen::log::error(oxen::log::Cat("verify"), "tx with empty inputs, rejected for tx id= {}", get_transaction_hash(tx));
return false;
}
}
@ -1552,20 +1542,20 @@ namespace cryptonote
{
if (tx.vin.size() != 0)
{
MERROR_VER("tx type: " << tx.type << " must have 0 inputs, received: " << tx.vin.size() << ", rejected for tx id = " << get_transaction_hash(tx));
oxen::log::error(oxen::log::Cat("verify"), "tx type: {} must have 0 inputs, received: {}, rejected for tx id = {}", tx.type, tx.vin.size(), get_transaction_hash(tx));
return false;
}
}
if(!check_inputs_types_supported(tx))
{
MERROR_VER("unsupported input types for tx id= " << get_transaction_hash(tx));
oxen::log::error(oxen::log::Cat("verify"), "unsupported input types for tx id= {}", get_transaction_hash(tx));
return false;
}
if(!check_outs_valid(tx))
{
MERROR_VER("tx with invalid outputs, rejected for tx id= " << get_transaction_hash(tx));
oxen::log::error(oxen::log::Cat("verify"), "tx with invalid outputs, rejected for tx id= {}", get_transaction_hash(tx));
return false;
}
@ -1573,14 +1563,14 @@ namespace cryptonote
{
if (tx.rct_signatures.outPk.size() != tx.vout.size())
{
MERROR_VER("tx with mismatched vout/outPk count, rejected for tx id= " << get_transaction_hash(tx));
oxen::log::error(oxen::log::Cat("verify"), "tx with mismatched vout/outPk count, rejected for tx id= {}", get_transaction_hash(tx));
return false;
}
}
if(!check_money_overflow(tx))
{
MERROR_VER("tx has money overflow, rejected for tx id= " << get_transaction_hash(tx));
oxen::log::error(oxen::log::Cat("verify"), "tx has money overflow, rejected for tx id= {}", get_transaction_hash(tx));
return false;
}
@ -1592,32 +1582,32 @@ namespace cryptonote
if(amount_in <= amount_out)
{
MERROR_VER("tx with wrong amounts: ins " << amount_in << ", outs " << amount_out << ", rejected for tx id= " << get_transaction_hash(tx));
oxen::log::error(oxen::log::Cat("verify"), "tx with wrong amounts: ins {}, outs {}, rejected for tx id= {}", amount_in, amount_out, get_transaction_hash(tx));
return false;
}
}
if(!keeped_by_block && get_transaction_weight(tx) >= m_blockchain_storage.get_current_cumulative_block_weight_limit() - COINBASE_BLOB_RESERVED_SIZE)
{
MERROR_VER("tx is too large " << get_transaction_weight(tx) << ", expected not bigger than " << m_blockchain_storage.get_current_cumulative_block_weight_limit() - COINBASE_BLOB_RESERVED_SIZE);
oxen::log::error(oxen::log::Cat("verify"), "tx is too large {}, expected not bigger than {}", get_transaction_weight(tx), m_blockchain_storage.get_current_cumulative_block_weight_limit() - COINBASE_BLOB_RESERVED_SIZE);
return false;
}
if(!check_tx_inputs_keyimages_diff(tx))
{
MERROR_VER("tx uses a single key image more than once");
oxen::log::error(oxen::log::Cat("verify"), "tx uses a single key image more than once");
return false;
}
if (!check_tx_inputs_ring_members_diff(tx))
{
MERROR_VER("tx uses duplicate ring members");
oxen::log::error(oxen::log::Cat("verify"), "tx uses duplicate ring members");
return false;
}
if (!check_tx_inputs_keyimages_domain(tx))
{
MERROR_VER("tx uses key image not in the valid domain");
oxen::log::error(oxen::log::Cat("verify"), "tx uses key image not in the valid domain");
return false;
}
@ -1644,7 +1634,7 @@ namespace cryptonote
"quorum.timestamp",
[this, pubkey](bool success, std::vector<std::string> data) {
const time_t local_seconds = time(nullptr);
MDEBUG("Timestamp message received: " << data[0] <<", local time is: " << local_seconds);
oxen::log::debug(logcat, "Timestamp message received: {}, local time is: ", data[0], local_seconds);
if(success){
int64_t received_seconds;
if (tools::parse_int(data[0],received_seconds)){
@ -1661,7 +1651,7 @@ namespace cryptonote
// Counts the number of times we have been out of sync
if (m_sn_times.failures() > (m_sn_times.size() * service_nodes::MAXIMUM_EXTERNAL_OUT_OF_SYNC/100)) {
MWARNING("service node time might be out of sync");
oxen::log::warning(logcat, "service node time might be out of sync");
// If we are out of sync record the other service node as in sync
m_service_node_list.record_timesync_status(pubkey, true);
} else {
@ -1773,7 +1763,7 @@ namespace cryptonote
if (cache_to > 0 && count > CACHE_EXCLUSIVE) {
cache_build_started = std::chrono::steady_clock::now();
m_coinbase_cache.building = true; // Block out other threads until we're done
MINFO("Starting slow cache build request for get_coinbase_tx_sum(" << start_offset << ", " << count << ")");
oxen::log::info(logcat, "Starting slow cache build request for get_coinbase_tx_sum({}, {})", start_offset, count);
}
}
}
@ -1810,8 +1800,8 @@ namespace cryptonote
if (m_coinbase_cache.building)
{
m_coinbase_cache.building = false;
MINFO("Finishing cache build for get_coinbase_tx_sum in " <<
std::chrono::duration<double>{std::chrono::steady_clock::now() - cache_build_started}.count() << "s");
oxen::log::info(logcat, "Finishing cache build for get_coinbase_tx_sum in {} s",
std::chrono::duration<double>{std::chrono::steady_clock::now() - cache_build_started}.count());
}
cache_to = 0;
}
@ -1904,7 +1894,7 @@ namespace cryptonote
}
if (relayed)
MGINFO("Submitted uptime-proof for Service Node (yours): " << m_service_keys.pub);
oxen::log::info(logcat, "Submitted uptime-proof for Service Node (yours): {}", m_service_keys.pub);
return true;
}
@ -1946,7 +1936,7 @@ namespace cryptonote
crypto::hash tx_hash;
if (!parse_and_validate_tx_from_blob(tx_blob, tx, tx_hash))
{
LOG_ERROR("Failed to parse relayed transaction");
oxen::log::error(logcat, "Failed to parse relayed transaction");
return crypto::null_hash;
}
txs.push_back(std::make_pair(tx_hash, std::move(tx_blob)));
@ -2065,7 +2055,7 @@ namespace cryptonote
std::vector<block> pblocks;
if (!prepare_handle_incoming_blocks(blocks, pblocks))
{
MERROR("Block found, but failed to prepare to add");
oxen::log::error(logcat, "Block found, but failed to prepare to add");
return false;
}
// add_new_block will verify block and set bvc.m_verification_failed accordingly
@ -2077,7 +2067,7 @@ namespace cryptonote
if (bvc.m_verifivation_failed)
{
bool pulse = cryptonote::block_has_pulse_components(b);
MERROR_VER((pulse ? "Pulse" : "Mined") << " block failed verification\n" << cryptonote::obj_to_json_str(b));
oxen::log::error(oxen::log::Cat("verify"), "{} block failed verification\n{}", (pulse ? "Pulse" : "Mined"), cryptonote::obj_to_json_str(b));
return false;
}
else if(bvc.m_added_to_main_chain)
@ -2087,7 +2077,7 @@ namespace cryptonote
m_blockchain_storage.get_transactions_blobs(b.tx_hashes, txs, &missed_txs);
if(missed_txs.size() && m_blockchain_storage.get_block_id_by_height(get_block_height(b)) != get_block_hash(b))
{
LOG_PRINT_L1("Block found but, seems that reorganize just happened after that, do not relay this block");
oxen::log::info(logcat, "Block found but, seems that reorganize just happened after that, do not relay this block");
return true;
}
CHECK_AND_ASSERT_MES(txs.size() == b.tx_hashes.size() && !missed_txs.size(), false, "can't find some transactions in found block:" << get_block_hash(b) << " txs.size()=" << txs.size()
@ -2157,7 +2147,7 @@ namespace cryptonote
}
if (((size_t)-1) <= 0xffffffff && block_blob.size() >= 0x3fffffff)
MWARNING("This block's size is " << block_blob.size() << ", closing on the 32 bit limit");
oxen::log::warning(logcat, "This block's size is {}, closing on the 32 bit limit", block_blob.size());
CHECK_AND_ASSERT_MES(update_checkpoints_from_json_file(), false, "One or more checkpoints loaded from json conflicted with existing checkpoints.");
@ -2167,7 +2157,7 @@ namespace cryptonote
crypto::hash block_hash;
if(!parse_and_validate_block_from_blob(block_blob, lb, block_hash))
{
LOG_PRINT_L1("Failed to parse and validate new block");
oxen::log::info(logcat, "Failed to parse and validate new block");
bvc.m_verifivation_failed = true;
return false;
}
@ -2192,7 +2182,7 @@ namespace cryptonote
// plus the tx hashes, the weight will typically be much larger than the blob size
if(block_blob.size() > m_blockchain_storage.get_current_cumulative_block_weight_limit() + BLOCK_SIZE_SANITY_LEEWAY)
{
LOG_PRINT_L1("WRONG BLOCK BLOB, sanity check failed on size " << block_blob.size() << ", rejected");
oxen::log::info(logcat, "WRONG BLOCK BLOB, sanity check failed on size {}, rejected", block_blob.size());
return false;
}
return true;
@ -2241,7 +2231,7 @@ namespace cryptonote
const std::chrono::seconds elapsed{std::time(nullptr) - last_ping};
if (elapsed > lifetime)
{
MWARNING("Have not heard from " << what << " " <<
oxen::log::warning(logcat, "Have not heard from {} {}", what,
(!last_ping ? "since starting" :
"since more than " + tools::get_human_readable_timespan(elapsed) + " ago"));
return false;
@ -2278,9 +2268,8 @@ namespace cryptonote
auto pubkey = m_service_node_list.get_pubkey_from_x25519(m_service_keys.pub_x25519);
if (pubkey != crypto::null_pkey && pubkey != m_service_keys.pub && m_service_node_list.is_service_node(pubkey, false /*don't require active*/))
{
MGINFO_RED(
"Failed to submit uptime proof: another service node on the network is using the same ed/x25519 keys as "
"this service node. This typically means both have the same 'key_ed25519' private key file.");
oxen::log::info(logcat, fmt::format(fg(fmt::terminal_color::red),
"Failed to submit uptime proof: another service node on the network is using the same ed/x25519 keys as this service node. This typically means both have the same 'key_ed25519' private key file."));
return;
}
@ -2295,12 +2284,7 @@ namespace cryptonote
if (pk != m_service_keys.pub && proof.proof->public_ip == m_sn_public_ip &&
(proof.proof->qnet_port == m_quorumnet_port || (
m_nettype != network_type::DEVNET && (proof.proof->storage_https_port == storage_https_port() || proof.proof->storage_omq_port == storage_omq_port()))))
MGINFO_RED(
"Another service node (" << pk << ") is broadcasting the same public IP and ports as this service node (" <<
epee::string_tools::get_ip_string_from_int32(m_sn_public_ip) << ":" << proof.proof->qnet_port << "[qnet], :" <<
proof.proof->storage_https_port << "[SS-HTTP], :" << proof.proof->storage_omq_port << "[SS-LMQ]). "
"This will lead to deregistration of one or both service nodes if not corrected. "
"(Do both service nodes have the correct IP for the service-node-public-ip setting?)");
oxen::log::info(logcat, fmt::format(fg(fmt::terminal_color::red), "Another service node ({}) is broadcasting the same public IP and ports as this service node ({}:{}[qnet], :{}[SS-HTTP], :{}[SS-LMQ]). This will lead to deregistration of one or both service nodes if not corrected. (Do both service nodes have the correct IP for the service-node-public-ip setting?)", pk, epee::string_tools::get_ip_string_from_int32(m_sn_public_ip), proof.proof->qnet_port, proof.proof->storage_https_port, proof.proof->storage_omq_port));
});
}
@ -2308,16 +2292,14 @@ namespace cryptonote
{
if (!check_external_ping(m_last_storage_server_ping, get_net_config().UPTIME_PROOF_FREQUENCY, "the storage server"))
{
MGINFO_RED(
"Failed to submit uptime proof: have not heard from the storage server recently. Make sure that it "
"is running! It is required to run alongside the Loki daemon");
oxen::log::info(logcat, fmt::format(fg(fmt::terminal_color::red),
"Failed to submit uptime proof: have not heard from the storage server recently. Make sure that it is running! It is required to run alongside the Loki daemon"));
return;
}
if (!check_external_ping(m_last_lokinet_ping, get_net_config().UPTIME_PROOF_FREQUENCY, "Lokinet"))
{
MGINFO_RED(
"Failed to submit uptime proof: have not heard from lokinet recently. Make sure that it "
"is running! It is required to run alongside the Loki daemon");
oxen::log::info(logcat, fmt::format(fg(fmt::terminal_color::red),
"Failed to submit uptime proof: have not heard from lokinet recently. Make sure that it is running! It is required to run alongside the Loki daemon"));
return;
}
}
@ -2341,15 +2323,14 @@ namespace cryptonote
main_message = "The daemon is running offline and will not attempt to sync to the Loki network.";
else
main_message = "The daemon will start synchronizing with the network. This may take a long time to complete.";
MGINFO_YELLOW("\n**********************************************************************\n"
<< main_message << "\n"
<< "\n"
<< "You can set the level of process detailization through \"set_log <level|categories>\" command,\n"
<< "where <level> is between 0 (no details) and 4 (very verbose), or custom category based levels (eg, *:WARNING).\n"
<< "\n"
<< "Use the \"help\" command to see the list of available commands.\n"
<< "Use \"help <command>\" to see a command's documentation.\n"
<< "**********************************************************************\n");
oxen::log::info(logcat, fmt::format(fg(fmt::terminal_color::yellow), "\n**********************************************************************\n\
{}\n\n\
You can set the level of process detailization through \"set_log <level|categories>\" command,\n\
where <level> is between 0 (no details) and 4 (very verbose), or custom category based levels (eg, *:WARNING).\n\
\n\
Use the \"help\" command to see the list of available commands.\n\
Use \"help <command>\" to see a command's documentation.\n\
**********************************************************************\n", main_message));
m_starter_message_showed = true;
}
@ -2380,10 +2361,7 @@ namespace cryptonote
{
uint64_t free_space = get_free_space();
if (free_space < 1ull * 1024 * 1024 * 1024) // 1 GB
{
const el::Level level = el::Level::Warning;
MCLOG_RED(level, "global", "Free space is below 1 GB on " << m_config_folder);
}
oxen::log::warning(logcat, fmt::format(fg(fmt::terminal_color::red), "Free space is below 1 GB on {}", m_config_folder));
return true;
}
//-----------------------------------------------------------------------------------------------
@ -2423,7 +2401,7 @@ namespace cryptonote
{
if (m_offline || m_nettype == network_type::FAKECHAIN || m_target_blockchain_height > get_current_blockchain_height() || m_target_blockchain_height == 0)
{
MDEBUG("Not checking block rate, offline or syncing");
oxen::log::debug(logcat, "Not checking block rate, offline or syncing");
return true;
}
@ -2440,10 +2418,13 @@ namespace cryptonote
const time_t time_boundary = now - static_cast<time_t>(seconds[n]);
for (time_t ts: timestamps) b += ts >= time_boundary;
const double p = probability(b, seconds[n] / tools::to_seconds(TARGET_BLOCK_TIME));
MDEBUG("blocks in the last " << seconds[n] / 60 << " minutes: " << b << " (probability " << p << ")");
oxen::log::debug(logcat, "blocks in the last {} minutes: {} (probability {})", seconds[n] / 60, b, p);
if (p < threshold)
{
MWARNING("There were " << b << (b == max_blocks_checked ? " or more" : "") << " blocks in the last " << seconds[n] / 60 << " minutes, there might be large hash rate changes, or we might be partitioned, cut off from the Loki network or under attack, or your computer's time is off. Or it could be just sheer bad luck.");
oxen::log::warning(logcat, "There were {}{} blocks in the last {} minutes, \
there might be large hash rate changes, or we might be partitioned, \
cut off from the Loki network or under attack, or your computer's time is off. \
Or it could be just sheer bad luck.", b, (b == max_blocks_checked ? " or more" : ""), seconds[n] / 60);
break; // no need to look further
}
}

View File

@ -41,6 +41,7 @@
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "crypto/crypto.h"
#include "crypto/hash.h"
#include "crypto/fmt.h"
#include "ringct/rctSigs.h"
#include "multisig/multisig.h"
#include "epee/int-util.h"
@ -77,7 +78,7 @@ namespace cryptonote
}
}
}
LOG_PRINT_L2("destinations include " << num_stdaddresses << " standard addresses and " << num_subaddresses << " subaddresses");
oxen::log::debug(globallogcat, "destinations include {} standard addresses and {} subaddresses", num_stdaddresses, num_subaddresses);
}
keypair get_deterministic_keypair_from_height(uint64_t height)
@ -126,7 +127,7 @@ namespace cryptonote
if (!get_deterministic_output_key(governance_wallet_address.address, gov_key, output_index, correct_key))
{
MERROR("Failed to generate deterministic output key for governance wallet output validation");
oxen::log::error(globallogcat, "Failed to generate deterministic output key for governance wallet output validation");
return false;
}
@ -288,7 +289,7 @@ namespace cryptonote
block_reward_parts reward_parts{};
if(!get_oxen_block_reward(median_weight, current_block_weight, already_generated_coins, hard_fork_version, reward_parts, block_reward_context))
{
LOG_PRINT_L0("Failed to calculate block reward");
oxen::log::warning(globallogcat, "Failed to calculate block reward");
return std::make_pair(false, block_rewards);
}
@ -458,7 +459,7 @@ namespace cryptonote
if (!get_deterministic_output_key(address, derivation_pair, it - rewards.begin(), out_eph_public_key))
{
MERROR("Failed to generate output one-time public key");
oxen::log::error(globallogcat, "Failed to generate output one-time public key");
return std::make_pair(false, block_rewards);
}
@ -514,13 +515,13 @@ namespace cryptonote
uint64_t base_reward, base_reward_unpenalized;
if (!get_base_block_reward(median_weight, current_block_weight, already_generated_coins, base_reward, base_reward_unpenalized, hard_fork_version, oxen_context.height))
{
MERROR("Failed to calculate base block reward");
oxen::log::error(globallogcat, "Failed to calculate base block reward");
return false;
}
if (base_reward == 0)
{
MERROR("Unexpected base reward of 0");
oxen::log::error(globallogcat, "Unexpected base reward of 0");
return false;
}
@ -574,9 +575,9 @@ namespace cryptonote
if (allocated > base_reward_unpenalized || remainder != 0)
{
if (allocated > base_reward_unpenalized)
MERROR("We allocated more reward " << cryptonote::print_money(allocated) << " than what was available " << cryptonote::print_money(base_reward_unpenalized));
oxen::log::error(globallogcat, "We allocated more reward {} than what was available {}", cryptonote::print_money(allocated), cryptonote::print_money(base_reward_unpenalized));
else
MERROR("We allocated reward but there was still " << cryptonote::print_money(remainder) << " oxen left to distribute.");
oxen::log::error(globallogcat, "We allocated reward but there was still {} oxen left to distribute.", cryptonote::print_money(remainder));
return false;
}
}
@ -617,7 +618,7 @@ namespace cryptonote
if (sources.empty())
{
LOG_ERROR("Empty sources");
oxen::log::error(globallogcat, "Empty sources");
return false;
}
@ -639,7 +640,7 @@ namespace cryptonote
if (tx_params.burn_percent)
{
LOG_ERROR("cannot construct tx: internal error: burn percent must be converted to fixed burn amount in the wallet");
oxen::log::error(globallogcat, "cannot construct tx: internal error: burn percent must be converted to fixed burn amount in the wallet");
return false;
}
@ -648,9 +649,11 @@ namespace cryptonote
if (tx.type == txtype::stake) {
crypto::secret_key tx_sk{tx_key};
bool added = hwdev.update_staking_tx_secret_key(tx_sk);
CHECK_AND_NO_ASSERT_MES(added, false, "Failed to add tx secret key to stake transaction");
if (!hwdev.update_staking_tx_secret_key(tx_sk))
{
oxen::log::warning(globallogcat, "Failed to add tx secret key to stake transaction");
return false;
}
cryptonote::add_tx_secret_key_to_tx_extra(tx.extra, tx_sk);
}
@ -667,17 +670,17 @@ namespace cryptonote
crypto::hash8 payment_id8 = null_hash8;
if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8))
{
LOG_PRINT_L2("Encrypting payment id " << payment_id8);
oxen::log::debug(globallogcat, "Encrypting payment id {}", payment_id8);
crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, change_addr);
if (view_key_pub == null_pkey)
{
LOG_ERROR("Destinations have to have exactly one output to support encrypted payment ids");
oxen::log::error(globallogcat, "Destinations have to have exactly one output to support encrypted payment ids");
return false;
}
if (!hwdev.encrypt_payment_id(payment_id8, view_key_pub, tx_key))
{
LOG_ERROR("Failed to encrypt payment id");
oxen::log::error(globallogcat, "Failed to encrypt payment id");
return false;
}
@ -686,10 +689,10 @@ namespace cryptonote
remove_field_from_tx_extra<tx_extra_nonce>(tx.extra);
if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce))
{
LOG_ERROR("Failed to add encrypted payment id to tx extra");
oxen::log::error(globallogcat, "Failed to add encrypted payment id to tx extra");
return false;
}
LOG_PRINT_L1("Encrypted payment ID: " << payment_id8);
oxen::log::info(globallogcat, "Encrypted payment ID: {}", payment_id8);
add_dummy_payment_id = false;
}
else if (get_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
@ -711,7 +714,7 @@ namespace cryptonote
crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, change_addr);
if (view_key_pub == null_pkey)
{
LOG_ERROR("Failed to get key to encrypt dummy payment id with");
oxen::log::error(globallogcat, "Failed to get key to encrypt dummy payment id with");
}
else
{
@ -719,7 +722,7 @@ namespace cryptonote
set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id8);
if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce))
{
LOG_ERROR("Failed to add dummy encrypted payment id to tx extra");
oxen::log::error(globallogcat, "Failed to add dummy encrypted payment id to tx extra");
// continue anyway
}
}
@ -727,7 +730,7 @@ namespace cryptonote
}
else
{
MWARNING("Failed to parse tx extra");
oxen::log::warning(globallogcat, "Failed to parse tx extra");
tx_extra_fields.clear();
}
@ -745,7 +748,7 @@ namespace cryptonote
++idx;
if(src_entr.real_output >= src_entr.outputs.size())
{
LOG_ERROR("real_output index (" << src_entr.real_output << ")bigger than output_keys.size()=" << src_entr.outputs.size());
oxen::log::error(globallogcat, "real_output index ({})bigger than output_keys.size()={}", src_entr.real_output, src_entr.outputs.size());
return false;
}
summary_inputs_money += src_entr.amount;
@ -757,18 +760,16 @@ namespace cryptonote
const auto& out_key = reinterpret_cast<const crypto::public_key&>(src_entr.outputs[src_entr.real_output].second.dest);
if(!generate_key_image_helper(sender_account_keys, subaddresses, out_key, src_entr.real_out_tx_key, src_entr.real_out_additional_tx_keys, src_entr.real_output_in_tx_index, in_ephemeral,img, hwdev))
{
LOG_ERROR("Key image generation failed!");
oxen::log::error(globallogcat, "Key image generation failed!");
return false;
}
//check that derivated key is equal with real output key (if non multisig)
if(!msout && !(in_ephemeral.pub == src_entr.outputs[src_entr.real_output].second.dest) )
{
LOG_ERROR("derived public key mismatch with output public key at index " << idx << ", real out " << src_entr.real_output << "!\nderived_key:"
<< tools::type_to_hex(in_ephemeral.pub) << "\nreal output_public_key:"
<< tools::type_to_hex(src_entr.outputs[src_entr.real_output].second.dest) );
LOG_ERROR("amount " << src_entr.amount << ", rct " << src_entr.rct);
LOG_ERROR("tx pubkey " << src_entr.real_out_tx_key << ", real_output_in_tx_index " << src_entr.real_output_in_tx_index);
oxen::log::error(globallogcat, "derived public key mismatch with output public key at index {}, real out {}!\nderived_key: {}\nreal output_public_key: {}", idx, src_entr.real_output, tools::type_to_hex(in_ephemeral.pub), tools::type_to_hex(src_entr.outputs[src_entr.real_output].second.dest));
oxen::log::error(globallogcat, "amount {}, rct {}", src_entr.amount, src_entr.rct);
oxen::log::error(globallogcat, "tx pubkey {}, real_output_in_tx_index {}", src_entr.real_out_tx_key, src_entr.real_output_in_tx_index);
return false;
}
@ -873,7 +874,7 @@ namespace cryptonote
keypair ephemeral_keys{};
if(!generate_key_image_helper(sender_account_keys, subaddresses, out_eph_public_key, txkey_pub, additional_tx_public_keys, output_index, ephemeral_keys, proof.key_image, hwdev))
{
LOG_ERROR("Key image generation failed for staking TX!");
oxen::log::error(globallogcat, "Key image generation failed for staking TX!");
return false;
}
@ -903,12 +904,12 @@ namespace cryptonote
remove_field_from_tx_extra<tx_extra_additional_pub_keys>(tx.extra);
LOG_PRINT_L2("tx pubkey: " << txkey_pub);
oxen::log::debug(globallogcat, "tx pubkey: {}", txkey_pub);
if (need_additional_txkeys)
{
LOG_PRINT_L2("additional tx pubkeys: ");
oxen::log::debug(globallogcat, "additional tx pubkeys: ");
for (size_t i = 0; i < additional_tx_public_keys.size(); ++i)
LOG_PRINT_L2(additional_tx_public_keys[i]);
oxen::log::debug(globallogcat, "{}", additional_tx_public_keys[i]);
add_additional_tx_pub_keys_to_extra(tx.extra, additional_tx_public_keys);
}
@ -918,7 +919,7 @@ namespace cryptonote
//check money
if(summary_outs_money > summary_inputs_money )
{
LOG_ERROR("Transaction inputs money ("<< summary_inputs_money << ") less than outputs money (" << summary_outs_money << ")");
oxen::log::error(globallogcat, "Transaction inputs money ({}) less than outputs money ({})", summary_inputs_money, summary_outs_money);
return false;
}
@ -928,7 +929,7 @@ namespace cryptonote
zero_secret_key &= (sender_account_keys.m_spend_secret_key.data[i] == 0);
if (zero_secret_key)
{
MDEBUG("Null secret key, skipping signatures");
oxen::log::debug(globallogcat, "Null secret key, skipping signatures");
}
uint64_t amount_in = 0, amount_out = 0;
@ -978,13 +979,13 @@ namespace cryptonote
{
if (amount_in < amount_out + tx_params.burn_fixed)
{
LOG_ERROR("invalid burn amount: tx does not have enough unspent funds available; amount_in: " << std::to_string(amount_in) << "; amount_out + tx_params.burn_fixed: " << std::to_string(amount_out) << " + " << std::to_string(tx_params.burn_fixed));
oxen::log::error(globallogcat, "invalid burn amount: tx does not have enough unspent funds available; amount_in: {}; amount_out + tx_params.burn_fixed: {} + {}", std::to_string(amount_in), std::to_string(amount_out), std::to_string(tx_params.burn_fixed));
return false;
}
remove_field_from_tx_extra<tx_extra_burn>(tx.extra); // doesn't have to be present (but the wallet puts a dummy here as a safety to avoid growing the tx)
if (!add_burned_amount_to_tx_extra(tx.extra, tx_params.burn_fixed))
{
LOG_ERROR("failed to add burn amount to tx extra");
oxen::log::error(globallogcat, "failed to add burn amount to tx extra");
return false;
}
}
@ -1006,7 +1007,7 @@ namespace cryptonote
CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout");
MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << "\n" << obj_to_json_str(tx) << "\n");
oxen::log::info(oxen::log::Cat("construct_tx"), "transaction_created: {}\n{}\n", get_transaction_hash(tx), obj_to_json_str(tx));
tx.invalidate_hashes();

View File

@ -3,6 +3,7 @@
#include <iterator>
#include <vector>
#include <algorithm>
#include <fmt/std.h>
#include "common/hex.h"
#include "cryptonote_config.h"
#include "oxen_name_system.h"
@ -34,14 +35,13 @@ extern "C"
#include <sodium/randombytes.h>
}
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "ons"
using cryptonote::hf;
namespace ons
{
static auto logcat = oxen::log::Cat("ons");
enum struct ons_sql_type
{
save_owner,
@ -361,7 +361,7 @@ bool sql_copy_blob(sql_compiled_statement& statement, I column, void *dest, size
auto blob = get<blob_view>(statement, column);
if (blob.data.size() != dest_size)
{
LOG_PRINT_L0("Unexpected blob size=" << blob.data.size() << ", in ONS DB does not match expected size=" << dest_size);
oxen::log::warning(logcat, "Unexpected blob size={}, in ONS DB does not match expected size={}", blob.data.size(), dest_size);
assert(blob.data.size() == dest_size);
return false;
}
@ -389,7 +389,7 @@ mapping_record sql_get_mapping_from_statement(sql_compiled_statement& statement)
auto value = get<std::string_view>(statement, mapping_record_column::encrypted_value);
if (value.size() > result.encrypted_value.buffer.size())
{
MERROR("Unexpected encrypted value blob with size=" << value.size() << ", in ONS db larger than the available size=" << result.encrypted_value.buffer.size());
oxen::log::error(logcat, "Unexpected encrypted value blob with size={}, in ONS db larger than the available size={}", value.size(), result.encrypted_value.buffer.size());
return result;
}
result.encrypted_value.len = value.size();
@ -435,7 +435,7 @@ bool sql_run_statement(ons_sql_type type, sql_compiled_statement& statement, voi
{
switch (type)
{
default: MERROR("Unhandled ons type enum with value: " << (int)type << ", in: " << __func__); break;
default: oxen::log::error(logcat, "Unhandled ons type enum with value: {}, in: {}", (int)type, __func__); break;
case ons_sql_type::internal_cmd: break;
case ons_sql_type::get_owner:
@ -499,7 +499,7 @@ bool sql_run_statement(ons_sql_type type, sql_compiled_statement& statement, voi
default:
{
LOG_PRINT_L1("Failed to execute statement: " << sqlite3_sql(statement.statement) <<", reason: " << sqlite3_errstr(step_result));
oxen::log::info(logcat, "Failed to execute statement: {}, reason: {}", sqlite3_sql(statement.statement), sqlite3_errstr(step_result));
infinite_loop = false;
break;
}
@ -541,7 +541,7 @@ bool sql_compiled_statement::compile(std::string_view query, bool optimise_for_m
#endif
if (prepare_result != SQLITE_OK) {
MERROR("Can not compile SQL statement:\n" << query << "\nReason: " << sqlite3_errstr(prepare_result));
oxen::log::error(logcat, "Can not compile SQL statement:\n{}\nReason: {}", query, sqlite3_errstr(prepare_result));
return false;
}
sqlite3_finalize(statement);
@ -568,7 +568,7 @@ sqlite3 *init_oxen_name_system(const fs::path& file_path, bool read_only)
int sql_init = sqlite3_initialize();
if (sql_init != SQLITE_OK)
{
MERROR("Failed to initialize sqlite3: " << sqlite3_errstr(sql_init));
oxen::log::error(logcat, "Failed to initialize sqlite3: {}", sqlite3_errstr(sql_init));
return nullptr;
}
@ -576,7 +576,7 @@ sqlite3 *init_oxen_name_system(const fs::path& file_path, bool read_only)
int sql_open = sqlite3_open_v2(file_path.u8string().c_str(), &result, flags, nullptr);
if (sql_open != SQLITE_OK)
{
MERROR("Failed to open ONS db at: " << file_path << ", reason: " << sqlite3_errstr(sql_open));
oxen::log::error(logcat, "Failed to open ONS db at: {}, reason: {}", file_path, sqlite3_errstr(sql_open));
return nullptr;
}
@ -591,7 +591,7 @@ sqlite3 *init_oxen_name_system(const fs::path& file_path, bool read_only)
int exec = sqlite3_exec(result, "PRAGMA journal_mode = WAL", nullptr, nullptr, nullptr);
if (exec != SQLITE_OK)
{
MERROR("Failed to set journal mode to WAL: " << sqlite3_errstr(exec));
oxen::log::error(logcat, "Failed to set journal mode to WAL: {}", sqlite3_errstr(exec));
return nullptr;
}
@ -605,7 +605,7 @@ sqlite3 *init_oxen_name_system(const fs::path& file_path, bool read_only)
exec = sqlite3_exec(result, "PRAGMA synchronous = NORMAL", nullptr, nullptr, nullptr);
if (exec != SQLITE_OK)
{
MERROR("Failed to set synchronous mode to NORMAL: " << sqlite3_errstr(exec));
oxen::log::error(logcat, "Failed to set synchronous mode to NORMAL: {}", sqlite3_errstr(exec));
return nullptr;
}
@ -664,7 +664,7 @@ std::string tx_extra_signature(std::string_view value, ons::generic_owner const
static_assert(sizeof(crypto::hash) == crypto_generichash_BYTES, "Using libsodium generichash for signature hash, require we fit into crypto::hash");
if (value.size() > mapping_value::BUFFER_SIZE)
{
MERROR("Unexpected value len=" << value.size() << " greater than the expected capacity=" << mapping_value::BUFFER_SIZE);
oxen::log::error(logcat, "Unexpected value len={} greater than the expected capacity={}", value.size(), mapping_value::BUFFER_SIZE);
return ""s;
}
@ -858,7 +858,7 @@ bool validate_ons_name(mapping_type type, std::string name, std::string *reason)
}
else
{
MERROR("Type not implemented");
oxen::log::error(logcat, "Type not implemented");
return false;
}
@ -1410,7 +1410,7 @@ bool mapping_value::encrypt(std::string_view name, const crypto::hash* name_hash
if (encryption_len > buffer.size())
{
MERROR("Encrypted value pre-allocated buffer too small=" << buffer.size() << ", required=" << encryption_len);
oxen::log::error(logcat, "Encrypted value pre-allocated buffer too small={}, required={}", buffer.size(), encryption_len);
return false;
}
@ -1482,18 +1482,18 @@ bool mapping_value::decrypt(std::string_view name, mapping_type type, const cryp
plain_len == WALLET_ACCOUNT_BINARY_LENGTH_INC_PAYMENT_ID || plain_len == WALLET_ACCOUNT_BINARY_LENGTH_NO_PAYMENT_ID) {
dec_length = plain_len;
} else {
MERROR("Invalid wallet mapping_type length passed to mapping_value::decrypt");
oxen::log::error(logcat, "Invalid wallet mapping_type length passed to mapping_value::decrypt");
return false;
}
break;
default: MERROR("Invalid mapping_type passed to mapping_value::decrypt");
default: oxen::log::error(logcat, "Invalid mapping_type passed to mapping_value::decrypt");
return false;
}
auto expected_len = dec_length + crypto_aead_xchacha20poly1305_ietf_ABYTES + crypto_aead_xchacha20poly1305_ietf_NPUBBYTES;
if (len != expected_len)
{
MERROR("Encrypted value size is invalid=" << len << ", expected=" << expected_len);
oxen::log::error(logcat, "Encrypted value size is invalid={}, expected={}", len, expected_len);
return false;
}
const auto& [enc, nonce] = value_nonce(type);
@ -1597,7 +1597,7 @@ CREATE INDEX IF NOT EXISTS mapping_type_name_exp ON mappings (type, name_hash, e
int table_created = sqlite3_exec(ons_db.db, BUILD_TABLE_SQL.c_str(), nullptr /*callback*/, nullptr /*callback context*/, &table_err_msg);
if (table_created != SQLITE_OK)
{
MERROR("Can not generate SQL table for ONS: " << (table_err_msg ? table_err_msg : "??"));
oxen::log::error(logcat, "Can not generate SQL table for ONS: {}", (table_err_msg ? table_err_msg : "??"));
sqlite3_free(table_err_msg);
return false;
}
@ -1627,7 +1627,7 @@ CREATE INDEX IF NOT EXISTS mapping_type_name_exp ON mappings (type, name_hash, e
"ALTER TABLE mappings ADD COLUMN update_height INTEGER NOT NULL DEFAULT register_height",
nullptr /*callback*/, nullptr /*callback ctx*/, nullptr /*errstr*/);
LOG_PRINT_L1("Migrating ONS mappings database to new format");
oxen::log::info(logcat, "Migrating ONS mappings database to new format");
const std::string migrate = R"(
BEGIN TRANSACTION;
ALTER TABLE mappings RENAME TO mappings_old;
@ -1646,7 +1646,7 @@ COMMIT TRANSACTION;
int migrated = sqlite3_exec(ons_db.db, migrate.c_str(), nullptr /*callback*/, nullptr /*callback context*/, &table_err_msg);
if (migrated != SQLITE_OK)
{
MERROR("Can not migrate SQL mappings table for ONS: " << (table_err_msg ? table_err_msg : "??"));
oxen::log::error(logcat, "Can not migrate SQL mappings table for ONS: {}", (table_err_msg ? table_err_msg : "??"));
sqlite3_free(table_err_msg);
return false;
}
@ -1687,14 +1687,14 @@ scoped_db_transaction::scoped_db_transaction(name_system_db &ons_db)
{
if (ons_db.transaction_begun)
{
MERROR("Failed to begin transaction, transaction exists previously that was not closed properly");
oxen::log::error(logcat, "Failed to begin transaction, transaction exists previously that was not closed properly");
return;
}
char *sql_err = nullptr;
if (sqlite3_exec(ons_db.db, "BEGIN;", nullptr, nullptr, &sql_err) != SQLITE_OK)
{
MERROR("Failed to begin transaction " << ", reason=" << (sql_err ? sql_err : "??"));
oxen::log::error(logcat, "Failed to begin transaction , reason={}", (sql_err ? sql_err : "??"));
sqlite3_free(sql_err);
return;
}
@ -1708,14 +1708,14 @@ scoped_db_transaction::~scoped_db_transaction()
if (!initialised) return;
if (!ons_db.transaction_begun)
{
MERROR("Trying to apply non-existent transaction (no prior history of a db transaction beginning) to the ONS DB");
oxen::log::error(logcat, "Trying to apply non-existent transaction (no prior history of a db transaction beginning) to the ONS DB");
return;
}
char *sql_err = nullptr;
if (sqlite3_exec(ons_db.db, commit ? "END;" : "ROLLBACK;", NULL, NULL, &sql_err) != SQLITE_OK)
{
MERROR("Failed to " << (commit ? "end " : "rollback ") << " transaction to ONS DB, reason=" << (sql_err ? sql_err : "??"));
oxen::log::error(logcat, "Failed to {} transaction to ONS DB, reason={}", (commit ? "end " : "rollback "), (sql_err ? sql_err : "??"));
sqlite3_free(sql_err);
return;
}
@ -1792,13 +1792,13 @@ AND NOT EXISTS (SELECT * FROM mappings WHERE owner.id = mappings.backup_owner_
{
if (!blockchain)
{
MERROR("Migration required, blockchain can not be nullptr");
oxen::log::error(logcat, "Migration required, blockchain can not be nullptr");
return false;
}
if (blockchain->get_db().is_read_only())
{
MERROR("DB is opened in read-only mode, unable to migrate ONS DB");
oxen::log::error(logcat, "DB is opened in read-only mode, unable to migrate ONS DB");
return false;
}
@ -1949,7 +1949,7 @@ std::optional<int64_t> add_or_get_owner_id(ons::name_system_db &ons_db, crypto::
{
if (!ons_db.save_owner(key, &result))
{
LOG_PRINT_L1("Failed to save ONS owner to DB tx: " << tx_hash << ", type: " << entry.type << ", name_hash: " << entry.name_hash << ", owner: " << entry.owner.to_string(ons_db.network_type()));
oxen::log::info(logcat, "Failed to save ONS owner to DB tx: {}, type: {}, name_hash: {}, owner: {}", tx_hash, entry.type, entry.name_hash, entry.owner.to_string(ons_db.network_type()));
return std::nullopt;
}
}
@ -1994,7 +1994,7 @@ SELECT type, name_hash, ?, ?)";
auto opt_id = add_or_get_owner_id(ons_db, tx_hash, entry, entry.owner);
if (!opt_id)
{
MERROR("Failed to add or get owner with key=" << entry.owner.to_string(ons_db.network_type()));
oxen::log::error(logcat, "Failed to add or get owner with key={}", entry.owner.to_string(ons_db.network_type()));
assert(opt_id);
return {};
}
@ -2009,7 +2009,7 @@ SELECT type, name_hash, ?, ?)";
auto opt_id = add_or_get_owner_id(ons_db, tx_hash, entry, entry.backup_owner);
if (!opt_id)
{
MERROR("Failed to add or get backup owner with key=" << entry.backup_owner.to_string(ons_db.network_type()));
oxen::log::error(logcat, "Failed to add or get backup owner with key={}", entry.backup_owner.to_string(ons_db.network_type()));
assert(opt_id);
return {};
}
@ -2046,7 +2046,7 @@ bool add_ons_entry(ons::name_system_db &ons_db, uint64_t height, cryptonote::tx_
auto owner_id = add_or_get_owner_id(ons_db, tx_hash, entry, entry.owner);
if (!owner_id)
{
MERROR("Failed to add or get owner with key=" << entry.owner.to_string(ons_db.network_type()));
oxen::log::error(logcat, "Failed to add or get owner with key={}", entry.owner.to_string(ons_db.network_type()));
assert(owner_id);
return false;
}
@ -2057,7 +2057,7 @@ bool add_ons_entry(ons::name_system_db &ons_db, uint64_t height, cryptonote::tx_
backup_owner_id = add_or_get_owner_id(ons_db, tx_hash, entry, entry.backup_owner);
if (!backup_owner_id)
{
MERROR("Failed to add or get backup owner with key=" << entry.backup_owner.to_string(ons_db.network_type()));
oxen::log::error(logcat, "Failed to add or get backup owner with key={}", entry.backup_owner.to_string(ons_db.network_type()));
assert(backup_owner_id);
return false;
}
@ -2067,7 +2067,7 @@ bool add_ons_entry(ons::name_system_db &ons_db, uint64_t height, cryptonote::tx_
if (expiry) *expiry += height;
if (!ons_db.save_mapping(tx_hash, entry, height, expiry, *owner_id, backup_owner_id))
{
LOG_PRINT_L1("Failed to save ONS entry to DB tx: " << tx_hash << ", type: " << entry.type << ", name_hash: " << entry.name_hash << ", owner: " << entry.owner.to_string(ons_db.network_type()));
oxen::log::info(logcat, "Failed to save ONS entry to DB tx: {}, type: {}, name_hash: {}, owner: {}", tx_hash, entry.type, entry.name_hash, entry.owner.to_string(ons_db.network_type()));
return false;
}
}
@ -2085,7 +2085,7 @@ bool add_ons_entry(ons::name_system_db &ons_db, uint64_t height, cryptonote::tx_
sql_compiled_statement statement{ons_db};
if (!statement.compile(sql, false /*optimise_for_multiple_usage*/))
{
MERROR("Failed to compile SQL statement for updating ONS record=" << sql);
oxen::log::error(logcat, "Failed to compile SQL statement for updating ONS record={}", sql);
return false;
}
@ -2123,7 +2123,7 @@ bool name_system_db::add_block(const cryptonote::block &block, const std::vector
std::string fail_reason;
if (!validate_ons_tx(block.major_version, height, tx, entry, &fail_reason))
{
MFATAL("ONS TX: Failed to validate for tx=" << get_transaction_hash(tx) << ". This should have failed validation earlier reason=" << fail_reason);
oxen::log::error(logcat, "ONS TX: Failed to validate for tx={}. This should have failed validation earlier reason={}", get_transaction_hash(tx), fail_reason);
assert("Failed to validate acquire name service. Should already have failed validation prior" == nullptr);
return false;
}

View File

@ -340,5 +340,21 @@ private:
sql_compiled_statement get_mappings_on_height_and_newer_sql{*this};
};
}; // namespace service_nodes
}; // namespace ons
template <>
struct fmt::formatter<ons::mapping_value> : fmt::formatter<std::string> {
auto format(ons::mapping_value v, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("{}", oxenc::to_hex(v.to_view())), ctx);
}
};
template <>
struct fmt::formatter<ons::mapping_type> : fmt::formatter<std::string> {
auto format(ons::mapping_type t, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("{}", ons::mapping_type_str(t)), ctx);
}
};
#endif // OXEN_NAME_SYSTEM_H

View File

@ -18,8 +18,7 @@ extern "C"
#include <sodium/crypto_generichash.h>
};
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "pulse"
static auto logcat = oxen::log::Cat("pulse");
// Deliberately makes pulse communications flakey for testing purposes:
//#define PULSE_TEST_CODE
@ -457,9 +456,7 @@ bool enforce_validator_participation_and_timeouts(round_context const &context,
if (timed_out && !all_received)
{
MDEBUG(log_prefix(context) << "Stage timed out: insufficient responses. Expected "
<< "(" << bitset_view16(validator_bitset).count() << ") " << bitset_view16(validator_bitset) << " received "
<< "(" << bitset_view16(stage.bitset).count() << ") " << bitset_view16(stage.bitset));
oxen::log::debug(logcat, "{}Stage timed out: insufficient responses. Expected ({}) {} received ({}) {}", log_prefix(context), bitset_view16(validator_bitset).count(), bitset_view16(validator_bitset).to_string(), bitset_view16(stage.bitset).count(), bitset_view16(stage.bitset).to_string());
return false;
}
@ -469,7 +466,7 @@ bool enforce_validator_participation_and_timeouts(round_context const &context,
bool unexpected_items = (stage.bitset | validator_bitset) != validator_bitset;
if (stage.msgs_received == 0 || unexpected_items)
{
MERROR(log_prefix(context) << "Internal error: expected bitset " << bitset_view16(validator_bitset) << ", but accepted and received " << bitset_view16(stage.bitset));
oxen::log::error(logcat, "{}Internal error: expected bitset {}, but accepted and received {}", log_prefix(context), bitset_view16(validator_bitset).to_string(), bitset_view16(stage.bitset).to_string());
return false;
}
@ -523,13 +520,13 @@ void pulse::handle_message(void *quorumnet_state, pulse::message const &msg)
// marked an error, just ignored.
print_err = false;
MTRACE(log_prefix(context) << "Received valid message from the past (round " << +msg.round << "), ignoring");
oxen::log::trace(logcat, "{}Received valid message from the past (round {}), ignoring", log_prefix(context), +msg.round);
break;
} // else: Message has unknown origins, it is not something we know how to validate.
}
if (print_err)
MERROR(sig_check_err);
oxen::log::error(logcat, sig_check_err);
return;
}
@ -539,7 +536,7 @@ void pulse::handle_message(void *quorumnet_state, pulse::message const &msg)
{
case pulse::message_type::invalid:
{
MTRACE(log_prefix(context) << "Received invalid message type, dropped");
oxen::log::trace(logcat, "{}Received invalid message type, dropped", log_prefix(context));
return;
}
@ -568,7 +565,7 @@ void pulse::handle_message(void *quorumnet_state, pulse::message const &msg)
auto &[entry, queued] = stage->queue.buffer[msg.quorum_position];
if (queued == queueing_state::empty)
{
MTRACE(log_prefix(context) << "Message received early " << msg_source_string(context, msg) << ", queueing until we're ready.");
oxen::log::trace(logcat, "{}Message received early {}, queueing until we're ready.", log_prefix(context), msg_source_string(context, msg));
stage->queue.count++;
entry = std::move(msg);
queued = queueing_state::received;
@ -585,15 +582,15 @@ void pulse::handle_message(void *quorumnet_state, pulse::message const &msg)
// locked in. Any stray messages from other validators are rejected.
if ((validator_bit & context.transient.wait_for_handshake_bitsets.best_bitset) == 0)
{
auto bitset_view = bitset_view16(context.transient.wait_for_handshake_bitsets.best_bitset);
MTRACE(log_prefix(context) << "Dropping " << msg_source_string(context, msg) << ". Not a locked in participant, bitset is " << bitset_view);
auto bitset_view = bitset_view16(context.transient.wait_for_handshake_bitsets.best_bitset).to_string();
oxen::log::trace(logcat, "{}Dropping {}. Not a locked in participant, bitset is {}", log_prefix(context), msg_source_string(context, msg), bitset_view);
return;
}
}
if (msg.quorum_position >= service_nodes::PULSE_QUORUM_NUM_VALIDATORS)
{
MTRACE(log_prefix(context) << "Dropping " << msg_source_string(context, msg) << ". Message quorum position indexes oob");
oxen::log::trace(logcat, "{}Dropping {}. Message quorum position indexes oob", log_prefix(context), msg_source_string(context, msg));
return;
}
@ -611,9 +608,7 @@ void pulse::handle_message(void *quorumnet_state, pulse::message const &msg)
auto &quorum = context.transient.send_and_wait_for_handshakes.data;
if (quorum[msg.quorum_position]) return;
quorum[msg.quorum_position] = true;
MTRACE(log_prefix(context) << "Received handshake with quorum position bit (" << msg.quorum_position << ") "
<< bitset_view16(validator_bit) << " saved to bitset "
<< bitset_view16(stage->bitset));
oxen::log::trace(logcat, "{}Received handshake with quorum position bit ({}) {} saved to bitset {}", log_prefix(context), msg.quorum_position, bitset_view16(validator_bit).to_string(), bitset_view16(stage->bitset).to_string());
}
break;
@ -634,14 +629,13 @@ void pulse::handle_message(void *quorumnet_state, pulse::message const &msg)
cryptonote::block block = {};
if (!cryptonote::t_serializable_object_from_blob(block, msg.block_template.blob))
{
MTRACE(log_prefix(context) << "Received unparsable pulse block template blob");
oxen::log::trace(logcat, "{}Received unparsable pulse block template blob", log_prefix(context));
return;
}
if (block.pulse.round != context.prepare_for_round.round)
{
MTRACE(log_prefix(context) << "Received pulse block template specifying different round " << +block.pulse.round
<< ", expected " << +context.prepare_for_round.round);
oxen::log::trace(logcat, "{}Received pulse block template specifying different round {}, expected {}", log_prefix(context), +block.pulse.round, +context.prepare_for_round.round);
return;
}
@ -649,7 +643,7 @@ void pulse::handle_message(void *quorumnet_state, pulse::message const &msg)
{
auto block_bitset = bitset_view16(block.pulse.validator_bitset);
auto our_bitset = bitset_view16(context.transient.wait_for_handshake_bitsets.best_bitset);
MTRACE(log_prefix(context) << "Received pulse block template specifying different validator handshake bitsets " << block_bitset << ", expected " << our_bitset);
oxen::log::trace(logcat, "{}Received pulse block template specifying different validator handshake bitsets {}, expected {}", log_prefix(context), block_bitset.to_string(), our_bitset.to_string());
return;
}
@ -677,9 +671,7 @@ void pulse::handle_message(void *quorumnet_state, pulse::message const &msg)
auto derived = blake2b_hash(msg.random_value.value.data, sizeof(msg.random_value.value.data));
if (derived != *hash)
{
MTRACE(log_prefix(context) << "Dropping " << msg_source_string(context, msg)
<< ". Rederived random value hash " << derived << " does not match original hash "
<< *hash);
oxen::log::trace(logcat, "{}Dropping {}. Rederived random value hash {} does not match original hash {}", log_prefix(context), msg_source_string(context, msg), derived, *hash);
return;
}
}
@ -700,10 +692,7 @@ void pulse::handle_message(void *quorumnet_state, pulse::message const &msg)
crypto::public_key const &validator_key = context.prepare_for_round.quorum.validators[msg.quorum_position];
if (!crypto::check_signature(final_block_hash, validator_key, msg.signed_block.signature_of_final_block_hash))
{
MTRACE(log_prefix(context) << "Dropping " << msg_source_string(context, msg)
<< ". Signature signing final block hash "
<< msg.signed_block.signature_of_final_block_hash
<< " does not validate with the Service Node");
oxen::log::trace(logcat, "{}Dropping {}. Signature signing final block hash {} does not validate with the Service Node", log_prefix(context), msg_source_string(context, msg), msg.signed_block.signature_of_final_block_hash);
return;
}
@ -1053,7 +1042,7 @@ round_state wait_for_next_block(uint64_t hf16_height, round_context &context, cr
if (context.wait_for_next_block.height == chain_height)
{
for (static uint64_t last_height = 0; last_height != chain_height; last_height = chain_height)
MDEBUG(log_prefix(context) << "Network is currently producing block " << chain_height << ", waiting until next block");
oxen::log::debug(logcat, "{}Network is currently producing block {}, waiting until next block", log_prefix(context), chain_height);
return round_state::wait_for_next_block;
}
@ -1061,7 +1050,7 @@ round_state wait_for_next_block(uint64_t hf16_height, round_context &context, cr
if (prev_hash == crypto::null_hash)
{
for (static uint64_t last_height = 0; last_height != chain_height; last_height = chain_height)
MDEBUG(log_prefix(context) << "Failed to query the block hash for height " << chain_height - 1);
oxen::log::debug(logcat, "{}Failed to query the block hash for height {}", log_prefix(context), chain_height - 1);
return round_state::wait_for_next_block;
}
@ -1073,7 +1062,7 @@ round_state wait_for_next_block(uint64_t hf16_height, round_context &context, cr
catch(std::exception const &e)
{
for (static uint64_t last_height = 0; last_height != chain_height; last_height = chain_height)
MDEBUG(log_prefix(context) << "Failed to query the block hash for height " << chain_height - 1);
oxen::log::debug(logcat, "{}Failed to query the block hash for height {}", log_prefix(context), chain_height - 1);
return round_state::wait_for_next_block;
}
@ -1081,7 +1070,7 @@ round_state wait_for_next_block(uint64_t hf16_height, round_context &context, cr
if (!get_round_timings(blockchain, chain_height, prev_timestamp, times))
{
for (static uint64_t last_height = 0; last_height != chain_height; last_height = chain_height)
MERROR(log_prefix(context) << "Failed to query the block data for Pulse timings");
oxen::log::error(logcat, "{}Failed to query the block data for Pulse timings", log_prefix(context));
return round_state::wait_for_next_block;
}
@ -1140,7 +1129,7 @@ round_state prepare_for_round(round_context &context, service_nodes::service_nod
if (round_usize > 255) // Network stalled
{
MINFO(log_prefix(context) << "Pulse has timed out, reverting to accepting miner blocks only.");
oxen::log::info(logcat, "{}Pulse has timed out, reverting to accepting miner blocks only.", log_prefix(context));
return goto_wait_for_next_block_and_clear_round_data(context);
}
@ -1175,11 +1164,11 @@ round_state prepare_for_round(round_context &context, service_nodes::service_nod
if (!service_nodes::verify_pulse_quorum_sizes(context.prepare_for_round.quorum))
{
MINFO(log_prefix(context) << "Insufficient Service Nodes to execute Pulse on height " << context.wait_for_next_block.height << ", we require a PoW miner block. Sleeping until next block.");
oxen::log::info(logcat, "{}Insufficient Service Nodes to execute Pulse on height {}, we require a PoW miner block. Sleeping until next block.", log_prefix(context), context.wait_for_next_block.height);
return goto_wait_for_next_block_and_clear_round_data(context);
}
MDEBUG(log_prefix(context) << "Generate Pulse quorum: " << context.prepare_for_round.quorum);
oxen::log::debug(logcat, "{}Generate Pulse quorum: {}", log_prefix(context), context.prepare_for_round.quorum);
//
// NOTE: Quorum participation
@ -1215,7 +1204,7 @@ round_state wait_for_round(round_context &context, cryptonote::Blockchain const
const auto curr_height = blockchain.get_current_blockchain_height(true /*lock*/);
if (context.wait_for_next_block.height != curr_height)
{
MDEBUG(log_prefix(context) << "Block height changed whilst waiting for round " << +context.prepare_for_round.round << ", restarting Pulse stages");
oxen::log::debug(logcat, "{}Block height changed whilst waiting for round {}, restarting Pulse stages", log_prefix(context), +context.prepare_for_round.round);
return goto_wait_for_next_block_and_clear_round_data(context);
}
@ -1223,7 +1212,7 @@ round_state wait_for_round(round_context &context, cryptonote::Blockchain const
if (auto now = pulse::clock::now(); now < start_time)
{
for (static uint64_t last_height = 0; last_height != context.wait_for_next_block.height; last_height = context.wait_for_next_block.height)
MINFO(log_prefix(context) << "Waiting for round " << +context.prepare_for_round.round << " to start in " << tools::friendly_duration(start_time - now));
oxen::log::info(logcat, "{}Waiting for round {} to start in {}", log_prefix(context), +context.prepare_for_round.round, tools::friendly_duration(start_time - now));
return round_state::wait_for_round;
}
@ -1236,7 +1225,7 @@ round_state wait_for_round(round_context &context, cryptonote::Blockchain const
size_t faulty_chance = tools::uniform_distribution_portable(tools::rng, 100);
if (faulty_chance < 10)
{
MDEBUG(log_prefix(context) << "FAULTY NODE ACTIVATED");
oxen::log::debug(logcat, "{}FAULTY NODE ACTIVATED", log_prefix(context));
return goto_preparing_for_next_round(context);
}
@ -1245,24 +1234,24 @@ round_state wait_for_round(round_context &context, cryptonote::Blockchain const
{
auto sleep_time = std::chrono::seconds(tools::uniform_distribution_portable(tools::rng, 20));
std::this_thread::sleep_for(sleep_time);
MDEBUG(log_prefix(context) << "SLEEP TIME ACTIVATED " << tools::to_seconds(sleep_time) << "s");
oxen::log::debug(logcat, "{}SLEEP TIME ACTIVATED {}s", log_prefix(context), tools::to_seconds(sleep_time));
}
}
#endif
if (context.prepare_for_round.participant == sn_type::validator)
{
MINFO(log_prefix(context) << "We are a pulse validator, sending handshake bit and collecting other handshakes.");
oxen::log::info(logcat, "{}We are a pulse validator, sending handshake bit and collecting other handshakes.", log_prefix(context));
return round_state::send_and_wait_for_handshakes;
}
else if (context.prepare_for_round.participant == sn_type::producer)
{
MINFO(log_prefix(context) << "We are the block producer for height " << context.wait_for_next_block.height << " in round " << +context.prepare_for_round.round << ", awaiting handshake bitsets.");
oxen::log::info(logcat, "{}We are the block producer for height {} in round {}, awaiting handshake bitsets.", log_prefix(context), context.wait_for_next_block.height, +context.prepare_for_round.round);
return round_state::wait_for_handshake_bitsets;
}
else
{
MDEBUG(log_prefix(context) << "Non-participant for round, waiting on next round or block.");
oxen::log::debug(logcat, "{}Non-participant for round, waiting on next round or block.", log_prefix(context));
return goto_preparing_for_next_round(context);
}
}
@ -1282,7 +1271,7 @@ round_state send_and_wait_for_handshakes(round_context &context, void *quorumnet
}
catch (std::exception const &e)
{
MERROR(log_prefix(context) << "Attempting to invoke and send a Pulse participation handshake unexpectedly failed. " << e.what());
oxen::log::error(logcat, "{}Attempting to invoke and send a Pulse participation handshake unexpectedly failed. {}", log_prefix(context), e.what());
return goto_preparing_for_next_round(context);
}
}
@ -1303,7 +1292,7 @@ round_state send_and_wait_for_handshakes(round_context &context, void *quorumnet
if (all_handshakes || timed_out)
{
bool missing_handshakes = timed_out && !all_handshakes;
MINFO(log_prefix(context) << "Collected validator handshakes " << bitset_view16(stage.bitset) << (missing_handshakes ? ", we timed out and some handshakes were not seen! " : ". ") << "Sending handshake bitset and collecting other validator bitsets.");
oxen::log::info(logcat, "{}Collected validator handshakes {}{}Sending handshake bitset and collecting other validator bitsets.", log_prefix(context), bitset_view16(stage.bitset).to_string(), (missing_handshakes ? ", we timed out and some handshakes were not seen! " : ". "));
return round_state::send_handshake_bitsets;
}
else
@ -1321,7 +1310,7 @@ round_state send_handshake_bitsets(round_context &context, void *quorumnet_state
}
catch(std::exception const &e)
{
MERROR(log_prefix(context) << "Attempting to invoke and send a Pulse validator bitset unexpectedly failed. " << e.what());
oxen::log::error(logcat, "{}Attempting to invoke and send a Pulse validator bitset unexpectedly failed. {}", log_prefix(context), e.what());
return goto_preparing_for_next_round(context);
}
}
@ -1351,7 +1340,7 @@ round_state wait_for_handshake_bitsets(round_context &context, service_nodes::se
best_bitset = *bitset;
count = num;
}
MTRACE(log_prefix(context) << "Collected from V[" << quorum_index << "], handshake bitset " << bitset_view16(*bitset));
oxen::log::trace(logcat, "{}Collected from V[{}], handshake bitset {}", log_prefix(context), quorum_index, bitset_view16(*bitset).to_string());
}
}
@ -1365,20 +1354,19 @@ round_state wait_for_handshake_bitsets(round_context &context, service_nodes::se
{
// Less than the threshold of the validators can come to agreement about
// which validators are online, we wait until the next round.
MDEBUG(log_prefix(context) << count << "/" << quorum.size()
<< " validators did not send any handshake bitset or sent an empty handshake "
"bitset and have failed to come to agreement. Waiting until next round.");
oxen::log::debug(logcat, "{}{}/{} \
validators did not send any handshake bitset or sent an empty handshake \
bitset and have failed to come to agreement. Waiting until next round.",
log_prefix(context), count, quorum.size());
}
else if (i_am_not_participating)
{
MDEBUG(log_prefix(context) << "The participating validator bitset " << bitset_view16(best_bitset)
<< " does not include us (quorum index " << context.prepare_for_round.my_quorum_position << "). Waiting until next round.");
oxen::log::debug(logcat, "{}The participating validator bitset {} does not include us (quorum index {}). Waiting until next round.", log_prefix(context), bitset_view16(best_bitset).to_string(), context.prepare_for_round.my_quorum_position);
}
else
{
// Can't come to agreement, see threshold comment above
MDEBUG(log_prefix(context) << "We heard back from less than " << service_nodes::PULSE_BLOCK_REQUIRED_SIGNATURES << " of the validators ("
<< count << "/" << quorum.size() << "). Waiting until next round.");
oxen::log::debug(logcat, "{}We heard back from less than {} of the validators ({}/{}). Waiting until next round.", log_prefix(context), service_nodes::PULSE_BLOCK_REQUIRED_SIGNATURES, count, quorum.size());
}
return goto_preparing_for_next_round(context);
@ -1386,9 +1374,8 @@ round_state wait_for_handshake_bitsets(round_context &context, service_nodes::se
context.transient.wait_for_handshake_bitsets.best_bitset = best_bitset;
context.transient.wait_for_handshake_bitsets.best_count = count;
MINFO(log_prefix(context) << count << "/" << quorum.size()
<< " validators agreed on the participating nodes in the quorum " << bitset_view16(best_bitset)
<< (context.prepare_for_round.participant == sn_type::producer
oxen::log::info(logcat, "{}{}/{} validators agreed on the participating nodes in the quorum {}{}", log_prefix(context), count, quorum.size(),
bitset_view16(best_bitset).to_string(), (context.prepare_for_round.participant == sn_type::producer
? ""
: ". Awaiting block template from block producer"));
@ -1409,14 +1396,14 @@ round_state send_block_template(round_context &context, void *quorumnet_state, s
// Invariants
if (list_state.empty())
{
MWARNING(log_prefix(context) << "Block producer (us) is not available on the service node list, waiting until next round");
oxen::log::warning(logcat, "{}Block producer (us) is not available on the service node list, waiting until next round", log_prefix(context));
return goto_preparing_for_next_round(context);
}
std::shared_ptr<const service_nodes::service_node_info> info = list_state[0].info;
if (!info->is_active())
{
MWARNING(log_prefix(context) << "Block producer (us) is not an active service node, waiting until next round");
oxen::log::warning(logcat, "{}Block producer (us) is not an active service node, waiting until next round", log_prefix(context));
return goto_preparing_for_next_round(context);
}
@ -1431,13 +1418,13 @@ round_state send_block_template(round_context &context, void *quorumnet_state, s
context.transient.wait_for_handshake_bitsets.best_bitset,
height))
{
MERROR(log_prefix(context) << "Failed to generate a block template, waiting until next round");
oxen::log::error(logcat, "{}Failed to generate a block template, waiting until next round", log_prefix(context));
return goto_preparing_for_next_round(context);
}
if (context.wait_for_next_block.height != height)
{
MDEBUG(log_prefix(context) << "Block height changed whilst preparing block template for round " << +context.prepare_for_round.round << ", restarting Pulse stages");
oxen::log::debug(logcat, "{}Block height changed whilst preparing block template for round {}, restarting Pulse stages", log_prefix(context), +context.prepare_for_round.round);
return goto_wait_for_next_block_and_clear_round_data(context);
}
}
@ -1449,7 +1436,7 @@ round_state send_block_template(round_context &context, void *quorumnet_state, s
crypto::generate_signature(msg_signature_hash(context.wait_for_next_block.top_hash, msg), key.pub, key.key, msg.signature);
// Send
MINFO(log_prefix(context) << "Validators are handshaken and ready, sending block template from producer (us) to validators.\n" << cryptonote::obj_to_json_str(block));
oxen::log::info(logcat, "{}Validators are handshaken and ready, sending block template from producer (us) to validators.\n{}", log_prefix(context), cryptonote::obj_to_json_str(block));
cryptonote::quorumnet_pulse_relay_message_to_quorum(quorumnet_state, msg, context.prepare_for_round.quorum, true /*block_producer*/);
return goto_preparing_for_next_round(context);
}
@ -1467,7 +1454,7 @@ round_state wait_for_block_template(round_context &context, service_nodes::servi
if (received)
{
cryptonote::block const &block = context.transient.wait_for_block_template.block;
MINFO(log_prefix(context) << "Valid block received: " << cryptonote::obj_to_json_str(context.transient.wait_for_block_template.block));
oxen::log::info(logcat, "{}Valid block received: {}", log_prefix(context), cryptonote::obj_to_json_str(context.transient.wait_for_block_template.block));
// Generate my random value and its hash
crypto::generate_random_bytes_thread_safe(sizeof(context.transient.random_value.send.data), context.transient.random_value.send.data.data);
@ -1476,7 +1463,7 @@ round_state wait_for_block_template(round_context &context, service_nodes::servi
}
else
{
MINFO(log_prefix(context) << "Timed out, block template was not received");
oxen::log::info(logcat, "{}Timed out, block template was not received", log_prefix(context));
return goto_preparing_for_next_round(context);
}
}
@ -1516,7 +1503,7 @@ round_state send_and_wait_for_random_value_hashes(round_context &context, servic
if (!enforce_validator_participation_and_timeouts(context, stage, node_list, timed_out, all_hashes))
return goto_preparing_for_next_round(context);
MINFO(log_prefix(context) << "Received " << bitset_view16(stage.bitset).count() << " random value hashes from " << bitset_view16(stage.bitset) << (timed_out ? ". We timed out and some hashes are missing" : ""));
oxen::log::info(logcat, "{}Received {} random value hashes from {}{}", log_prefix(context), bitset_view16(stage.bitset).count(), bitset_view16(stage.bitset).to_string(), (timed_out ? ". We timed out and some hashes are missing" : ""));
return round_state::send_and_wait_for_random_value;
}
@ -1574,7 +1561,7 @@ round_state send_and_wait_for_random_value(round_context &context, service_nodes
string.data()[i] = '.';
#endif
MDEBUG(log_prefix(context) << "Final random value seeding with V[" << index << "] " << string.view());
oxen::log::debug(logcat, "{}Final random value seeding with V[{}] {}", log_prefix(context), index, string.view());
crypto_generichash_update(&state, random_value->data, sizeof(random_value->data));
}
}
@ -1596,7 +1583,7 @@ round_state send_and_wait_for_random_value(round_context &context, service_nodes
crypto::hash const &final_block_hash = cryptonote::get_block_hash(final_block);
crypto::generate_signature(final_block_hash, key.pub, key.key, context.transient.signed_block.send.data);
MINFO(log_prefix(context) << "Block final random value " << oxenc::to_hex(tools::view_guts(final_block.pulse.random_value.data)) << " generated from validators " << bitset_view16(stage.bitset));
oxen::log::info(logcat, "{}Block final random value {} generated from validators {}", log_prefix(context), oxenc::to_hex(tools::view_guts(final_block.pulse.random_value.data)), bitset_view16(stage.bitset).to_string());
return round_state::send_and_wait_for_signed_blocks;
}
@ -1658,12 +1645,12 @@ round_state send_and_wait_for_signed_blocks(round_context &context, service_node
uint16_t validator_index = indices[index];
auto const &signature = quorum[validator_index];
assert(signature);
MDEBUG(log_prefix(context) << "Signature added: " << validator_index << ":" << context.prepare_for_round.quorum.validators[validator_index] << ", " << *signature);
oxen::log::debug(logcat, "{}Signature added: {}:{}, {}", log_prefix(context), validator_index, context.prepare_for_round.quorum.validators[validator_index], *signature);
final_block.signatures.emplace_back(validator_index, *signature);
}
// Propagate Final Block
MDEBUG(log_prefix(context) << "Final signed block constructed\n" << cryptonote::obj_to_json_str(final_block));
oxen::log::debug(logcat, "{}Final signed block constructed\n{}", log_prefix(context), cryptonote::obj_to_json_str(final_block));
cryptonote::block_verification_context bvc = {};
if (!core.handle_block_found(final_block, bvc))
return goto_preparing_for_next_round(context);
@ -1686,14 +1673,14 @@ void pulse::main(void *quorumnet_state, cryptonote::core &core)
if (!hf16)
{
for (static bool once = true; once; once = !once)
MERROR("Pulse: HF16 is not defined, pulse worker waiting");
oxen::log::error(logcat, "Pulse: HF16 is not defined, pulse worker waiting");
return;
}
if (uint64_t height = blockchain.get_current_blockchain_height(true /*lock*/); height < *hf16)
{
for (static bool once = true; once; once = !once)
MDEBUG("Pulse: Network at block " << height << " is not ready for Pulse until block " << *hf16 << ", waiting");
oxen::log::debug(logcat, "Pulse: Network at block {} is not ready for Pulse until block {}, waiting", height, *hf16);
return;
}

File diff suppressed because it is too large Load Diff

View File

@ -39,13 +39,12 @@
#include "epee/net/local_ip.h"
#include <oxenc/endian.h>
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "quorum_cop"
using cryptonote::hf;
namespace service_nodes
{
static auto logcat = oxen::log::Cat("quorum_cop");
std::optional<std::vector<std::string_view>> service_node_test_results::why() const
{
if (passed())
@ -112,23 +111,20 @@ namespace service_nodes
if (check_uptime_obligation && time_since_last_uptime_proof > netconf.UPTIME_PROOF_VALIDITY)
{
LOG_PRINT_L1(
"Service Node: " << pubkey << ", failed uptime proof obligation check: the last uptime proof (" <<
tools::get_human_readable_timespan(time_since_last_uptime_proof) << ") was older than max validity (" <<
tools::get_human_readable_timespan(netconf.UPTIME_PROOF_VALIDITY) << ")");
oxen::log::info(logcat, "Service Node: {}, failed uptime proof obligation check: the last uptime proof ({}) was older than max validity ({})", pubkey, tools::get_human_readable_timespan(time_since_last_uptime_proof), tools::get_human_readable_timespan(netconf.UPTIME_PROOF_VALIDITY));
result.uptime_proved = false;
}
if (!ss_reachable)
{
LOG_PRINT_L1("Service Node storage server is not reachable for node: " << pubkey);
oxen::log::info(logcat, "Service Node storage server is not reachable for node: {}", pubkey);
result.storage_server_reachable = false;
}
// TODO: perhaps come back and make this activate on some "soft fork" height before HF19?
if (!lokinet_reachable && hf_version >= hf::hf19_reward_batching)
{
LOG_PRINT_L1("Service Node lokinet is not reachable for node: " << pubkey);
oxen::log::info(logcat, "Service Node lokinet is not reachable for node: {}", pubkey);
result.lokinet_reachable = false;
}
@ -150,24 +146,24 @@ namespace service_nodes
{
if (check_checkpoint_obligation && checkpoint_participation.failures() > CHECKPOINT_MAX_MISSABLE_VOTES)
{
LOG_PRINT_L1("Service Node: " << pubkey << ", failed checkpoint obligation check");
oxen::log::info(logcat, "Service Node: {}, failed checkpoint obligation check", pubkey);
result.checkpoint_participation = false;
}
if (pulse_participation.failures() > PULSE_MAX_MISSABLE_VOTES)
{
LOG_PRINT_L1("Service Node: " << pubkey << ", failed pulse obligation check");
oxen::log::info(logcat, "Service Node: {}, failed pulse obligation check", pubkey);
result.pulse_participation = false;
}
if (timestamp_participation.failures() > TIMESTAMP_MAX_MISSABLE_VOTES)
{
LOG_PRINT_L1("Service Node: " << pubkey << ", failed timestamp obligation check");
oxen::log::info(logcat, "Service Node: {}, failed timestamp obligation check", pubkey);
result.timestamp_participation = false;
}
if (timesync_status.failures() > TIMESYNC_MAX_UNSYNCED_VOTES)
{
LOG_PRINT_L1("Service Node: " << pubkey << ", failed timesync obligation check");
oxen::log::info(logcat, "Service Node: {}, failed timesync obligation check", pubkey);
result.timesync_status = false;
}
}
@ -186,8 +182,8 @@ namespace service_nodes
{
if (!by_pop_blocks)
{
LOG_ERROR("The blockchain was detached to height: " << height << ", but quorum cop has already processed votes for obligations up to " << m_obligations_height);
LOG_ERROR("This implies a reorg occured that was over " << REORG_SAFETY_BUFFER_BLOCKS << ". This should rarely happen! Please report this to the devs.");
oxen::log::error(logcat, "The blockchain was detached to height: {}, but quorum cop has already processed votes for obligations up to {}", height, m_obligations_height);
oxen::log::error(logcat, "This implies a reorg occured that was over {}. This should rarely happen! Please report this to the devs.", REORG_SAFETY_BUFFER_BLOCKS);
}
m_obligations_height = height;
}
@ -196,8 +192,8 @@ namespace service_nodes
{
if (!by_pop_blocks)
{
LOG_ERROR("The blockchain was detached to height: " << height << ", but quorum cop has already processed votes for checkpointing up to " << m_last_checkpointed_height);
LOG_ERROR("This implies a reorg occured that was over " << REORG_SAFETY_BUFFER_BLOCKS << ". This should rarely happen! Please report this to the devs.");
oxen::log::error(logcat, "The blockchain was detached to height: {}, but quorum cop has already processed votes for checkpointing up to {}", height, m_last_checkpointed_height);
oxen::log::error(logcat, "This implies a reorg occured that was over {}. This should rarely happen! Please report this to the devs.", REORG_SAFETY_BUFFER_BLOCKS);
}
m_last_checkpointed_height = height - (height % CHECKPOINT_INTERVAL);
}
@ -261,7 +257,7 @@ namespace service_nodes
default:
{
assert("Unhandled quorum type " == 0);
LOG_ERROR("Unhandled quorum type with value: " << (int)type);
oxen::log::error(logcat, "Unhandled quorum type with value: {}", (int)type);
} break;
case quorum_type::obligations:
@ -313,7 +309,7 @@ namespace service_nodes
if (!quorum)
{
// TODO(oxen): Fatal error
LOG_ERROR("Obligations quorum for height: " << m_obligations_height << " was not cached in daemon!");
oxen::log::error(logcat, "Obligations quorum for height: {} was not cached in daemon!", m_obligations_height);
continue;
}
@ -352,12 +348,12 @@ namespace service_nodes
if (passed) {
if (info.is_decommissioned()) {
vote_for_state = new_state::recommission;
LOG_PRINT_L2("Decommissioned service node " << quorum->workers[node_index] << " is now passing required checks; voting to recommission");
oxen::log::debug(logcat, "Decommissioned service node {} is now passing required checks; voting to recommission", quorum->workers[node_index]);
} else if (!test_results.single_ip) {
// Don't worry about this if the SN is getting recommissioned (above) -- it'll
// already reenter at the bottom.
vote_for_state = new_state::ip_change_penalty;
LOG_PRINT_L2("Service node " << quorum->workers[node_index] << " was observed with multiple IPs recently; voting to reset reward position");
oxen::log::debug(logcat, "Service node {} was observed with multiple IPs recently; voting to reset reward position", quorum->workers[node_index]);
} else {
good++;
continue;
@ -376,46 +372,35 @@ namespace service_nodes
if (info.is_decommissioned()) {
if (credit >= 0) {
LOG_PRINT_L2("Decommissioned service node "
<< quorum->workers[node_index]
<< " is still not passing required checks, but has remaining credit (" << credit
<< " blocks); abstaining (to leave decommissioned)");
oxen::log::debug(logcat, "Decommissioned service node {} is still not passing required checks, but has remaining credit ({} blocks); abstaining (to leave decommissioned)", quorum->workers[node_index], credit);
continue;
}
LOG_PRINT_L2("Decommissioned service node " << quorum->workers[node_index] << " has no remaining credit; voting to deregister");
oxen::log::debug(logcat, "Decommissioned service node {} has no remaining credit; voting to deregister", quorum->workers[node_index]);
vote_for_state = new_state::deregister; // Credit ran out!
} else {
if (credit >= DECOMMISSION_MINIMUM) {
vote_for_state = new_state::decommission;
LOG_PRINT_L2("Service node "
<< quorum->workers[node_index]
<< " has stopped passing required checks, but has sufficient earned credit (" << credit << " blocks) to avoid deregistration; voting to decommission");
oxen::log::debug(logcat, "Service node {} has stopped passing required checks, but has sufficient earned credit ({} blocks) to avoid deregistration; voting to decommission", quorum->workers[node_index], credit);
} else {
vote_for_state = new_state::deregister;
LOG_PRINT_L2("Service node "
<< quorum->workers[node_index]
<< " has stopped passing required checks, but does not have sufficient earned credit ("
<< credit << " blocks, " << DECOMMISSION_MINIMUM
<< " required) to decommission; voting to deregister");
oxen::log::debug(logcat, "Service node {} has stopped passing required checks, but does not ahve sufficient earned credit ({} blocks, {} required) to decommission; voting to deregister", quorum->workers[node_index], credit, DECOMMISSION_MINIMUM);
}
}
}
if (vote_for_state == new_state::deregister && height - *cryptonote::get_hard_fork_heights(m_core.get_nettype(), hf_version).first < netconf.HARDFORK_DEREGISTRATION_GRACE_PERIOD) {
LOG_PRINT_L2("Decommissioned service node "
<< quorum->workers[node_index]
<< " is still not passing required checks, and has no remaining credits left. However it is within the grace period of a hardfork so has not been deregistered.");
oxen::log::debug(logcat, "Decommissioned service node {} is still not passing required checks, and has no remaining credits left. However it is within the grace period of a hardfork so has not been deregistered.", quorum->workers[node_index]);
continue;
}
quorum_vote_t vote = service_nodes::make_state_change_vote(m_obligations_height, static_cast<uint16_t>(index_in_group), node_index, vote_for_state, reason, my_keys);
cryptonote::vote_verification_context vvc;
if (!handle_vote(vote, vvc))
LOG_ERROR("Failed to add state change vote; reason: " << print_vote_verification_context(vvc, &vote));
oxen::log::error(logcat, "Failed to add state change vote; reason: {}", print_vote_verification_context(vvc, &vote));
}
if (good > 0)
LOG_PRINT_L2(good << " of " << total << " service nodes are active and passing checks; no state change votes required");
oxen::log::debug(logcat, "{} of {} service nodes are active and passing checks; no state change votes required", good, total);
}
else if (!tested_myself_once_per_block && (find_index_in_quorum_group(quorum->workers, my_keys.pub) >= 0))
{
@ -439,16 +424,15 @@ namespace service_nodes
if (print_failings)
{
LOG_PRINT_L0(
(info.is_decommissioned()
oxen::log::warning(logcat, "{}{}", (info.is_decommissioned()
? "Service Node (yours) is currently decommissioned and being tested in quorum: "
: "Service Node (yours) is active but is not passing tests for quorum: ")
<< m_obligations_height);
: "Service Node (yours) is active but is not passing tests for quorum: "),
m_obligations_height);
if (auto why = my_test_results.why())
LOG_PRINT_L0(tools::join("\n", *why));
oxen::log::warning(logcat, tools::join("\n", *why));
else
LOG_PRINT_L0("Service Node is passing all local tests");
LOG_PRINT_L0("(Note that some tests, such as storage server and lokinet reachability, can only assessed by remote service nodes)");
oxen::log::warning(logcat, "Service Node is passing all local tests");
oxen::log::warning(logcat, "(Note that some tests, such as storage server and lokinet reachability, can only assessed by remote service nodes)");
}
}
}
@ -482,7 +466,7 @@ namespace service_nodes
if (!quorum)
{
// TODO(oxen): Fatal error
LOG_ERROR("Checkpoint quorum for height: " << m_last_checkpointed_height << " was not cached in daemon!");
oxen::log::error(logcat, "Checkpoint quorum for height: {} was not cached in daemon!", m_last_checkpointed_height);
continue;
}
@ -496,7 +480,7 @@ namespace service_nodes
quorum_vote_t vote = make_checkpointing_vote(checkpointed_height_hf_version, block_hash, m_last_checkpointed_height, static_cast<uint16_t>(index_in_group), my_keys);
cryptonote::vote_verification_context vvc = {};
if (!handle_vote(vote, vvc))
LOG_ERROR("Failed to add checkpoint vote; reason: " << print_vote_verification_context(vvc, &vote));
oxen::log::error(logcat, "Failed to add checkpoint vote; reason: {}", print_vote_verification_context(vvc, &vote));
}
}
}
@ -521,7 +505,7 @@ namespace service_nodes
{
if (votes.size() < STATE_CHANGE_MIN_VOTES_TO_CHANGE_STATE)
{
LOG_PRINT_L2("Don't have enough votes yet to submit a state change transaction: have " << votes.size() << " of " << STATE_CHANGE_MIN_VOTES_TO_CHANGE_STATE << " required");
oxen::log::debug(logcat, "Don't have enough votes yet to submit a state change transaction: have {} of {} required", votes.size(), STATE_CHANGE_MIN_VOTES_TO_CHANGE_STATE);
return true;
}
@ -567,16 +551,12 @@ namespace service_nodes
bool result = core.handle_incoming_tx(cryptonote::tx_to_blob(state_change_tx), tvc, cryptonote::tx_pool_options::new_tx());
if (!result || tvc.m_verifivation_failed)
{
LOG_PRINT_L1("A full state change tx for height: " << vote.block_height <<
" and service node: " << vote.state_change.worker_index <<
" could not be verified and was not added to the memory pool, reason: " <<
print_tx_verification_context(tvc, &state_change_tx));
oxen::log::info(logcat, "A full state change tx for height: {} and service node: {} could not be verified and was not added to the memory pool, reason: {}", vote.block_height, vote.state_change.worker_index, print_tx_verification_context(tvc, &state_change_tx));
return false;
}
}
else
LOG_PRINT_L1("Failed to add state change to tx extra for height: "
<< vote.block_height << " and service node: " << vote.state_change.worker_index);
oxen::log::info(logcat, "Failed to add state change to tx extra for height: {} and service node: {}", vote.block_height, vote.state_change.worker_index);
return true;
}
@ -585,7 +565,7 @@ namespace service_nodes
{
if (votes.size() < CHECKPOINT_MIN_VOTES)
{
LOG_PRINT_L2("Don't have enough votes yet to submit a checkpoint: have " << votes.size() << " of " << CHECKPOINT_MIN_VOTES << " required");
oxen::log::debug(logcat, "Don't have enough votes yet to submit a checkpoint: have {} of {} required", votes.size(), CHECKPOINT_MIN_VOTES);
return true;
}
@ -677,7 +657,7 @@ namespace service_nodes
{
default:
{
LOG_PRINT_L1("Unhandled vote type with value: " << (int)vote.type);
oxen::log::info(logcat, "Unhandled vote type with value: {}", (int)vote.type);
assert("Unhandled vote type" == 0);
return false;
};

View File

@ -34,6 +34,7 @@
#include "cryptonote_core/service_node_voting.h"
#include <cassert>
#include <mutex>
#include <fmt/format.h>
namespace cryptonote
{
@ -50,6 +51,16 @@ namespace service_nodes
{
std::vector<crypto::public_key> validators; // Array of public keys identifying service nodes who validate and sign.
std::vector<crypto::public_key> workers; // Array of public keys of tested service nodes (if applicable).
//
inline std::string to_string() const
{
std::stringstream result;
for (size_t i = 0; i < validators.size(); i++)
result << "V[" << i << "] " << validators[i] << "\n";
for (size_t i = 0; i < workers.size(); i++)
result << "W[" << std::to_string(i) + "] " << workers[i] << "\n";
return result.str();
};
BEGIN_SERIALIZE()
FIELD(validators)
@ -59,11 +70,10 @@ namespace service_nodes
inline std::ostream &operator<<(std::ostream &os, quorum const &q)
{
for (size_t i = 0; i < q.validators.size(); i++) os << "V[" << i << "] " << q.validators[i] << "\n";
for (size_t i = 0; i < q.workers.size(); i++) os << "W[" << i << "] " << q.workers[i] << "\n";
return os;
return os << q.to_string();
}
struct quorum_manager
{
std::shared_ptr<const quorum> obligations;
@ -79,7 +89,7 @@ namespace service_nodes
else if (type == quorum_type::checkpointing) return checkpointing;
else if (type == quorum_type::blink) return blink;
else if (type == quorum_type::pulse) return pulse;
MERROR("Developer error: Unhandled quorum enum with value: " << (size_t)type);
oxen::log::error(oxen::log::Cat("quorum_cop"), "Developer error: Unhandled quorum enum with value: {}", (size_t)type);
assert(!"Developer error: Unhandled quorum enum with value: ");
return nullptr;
}
@ -155,3 +165,11 @@ namespace service_nodes
*/
uint64_t quorum_checksum(const std::vector<crypto::public_key> &pubkeys, size_t offset = 0);
}
template <>
struct fmt::formatter<service_nodes::quorum> : fmt::formatter<std::string> {
auto format(service_nodes::quorum quorum, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("{}", quorum.to_string()), ctx);
}
};

View File

@ -16,6 +16,8 @@ using cryptonote::hf;
namespace service_nodes {
static auto logcat = oxen::log::Cat("service_nodes");
uint64_t get_staking_requirement(cryptonote::network_type nettype, hf hardfork)
{
assert(hardfork >= hf::hf16_pulse);
@ -110,11 +112,11 @@ bool check_service_node_portions(hf hf_version, const std::vector<std::pair<cryp
hf_version = hf::hf18;
else if (hf_version > hf::hf19_reward_batching)
{
LOG_PRINT_L1("Registration tx rejected: portions-based registrations not permitted after HF19");
oxen::log::info(logcat, "Registration tx rejected: portions-based registrations not permitted after HF19");
return false;
}
if (portions.size() > oxen::MAX_CONTRIBUTORS_V1) {
LOG_PRINT_L1("Registration tx rejected: too many contributors (" << portions.size() << " > " << oxen::MAX_CONTRIBUTORS_V1 << ")");
oxen::log::info(logcat, "Registration tx rejected: too many contributors ({} > {})", portions.size(), oxen::MAX_CONTRIBUTORS_V1);
return false;
}
@ -125,11 +127,11 @@ bool check_service_node_portions(hf hf_version, const std::vector<std::pair<cryp
const uint64_t min_portions = get_min_node_contribution(hf_version, cryptonote::old::STAKING_PORTIONS, reserved, i);
if (portions[i].second < min_portions) {
LOG_PRINT_L1("Registration tx rejected: portion " << i << " too small (" << portions[i].second << " < " << min_portions << ")");
oxen::log::info(logcat, "Registration tx rejected: portion {} too small ({} < {})", i, portions[i].second, min_portions);
return false;
}
if (portions[i].second > remaining) {
LOG_PRINT_L1("Registration tx rejected: portion " << i << " exceeds available portions");
oxen::log::info(logcat, "Registration tx rejected: portion {} exceeds available portions", i);
return false;
}
@ -143,11 +145,11 @@ bool check_service_node_portions(hf hf_version, const std::vector<std::pair<cryp
bool check_service_node_stakes(hf hf_version, cryptonote::network_type nettype, uint64_t staking_requirement, const std::vector<std::pair<cryptonote::account_public_address, uint64_t>>& stakes)
{
if (hf_version < hf::hf19_reward_batching) {
LOG_PRINT_L1("Registration tx rejected: amount-based registrations not accepted before HF19");
oxen::log::info(logcat, "Registration tx rejected: amount-based registrations not accepted before HF19");
return false; // OXEN-based registrations not accepted before HF19
}
if (stakes.size() > oxen::MAX_CONTRIBUTORS_HF19) {
LOG_PRINT_L1("Registration tx rejected: too many contributors (" << stakes.size() << " > " << oxen::MAX_CONTRIBUTORS_HF19 << ")");
oxen::log::info(logcat, "Registration tx rejected: too many contributors ({} > {})", stakes.size(), oxen::MAX_CONTRIBUTORS_HF19);
return false;
}
@ -161,11 +163,11 @@ bool check_service_node_stakes(hf hf_version, cryptonote::network_type nettype,
const uint64_t min_stake = i == 0 ? operator_requirement : get_min_node_contribution(hf_version, staking_requirement, reserved, i);
if (stakes[i].second < min_stake) {
LOG_PRINT_L1("Registration tx rejected: stake " << i << " too small (" << stakes[i].second << " < " << min_stake << ")");
oxen::log::info(logcat, "Registration tx rejected: stake {} too small ({} < {})", i, stakes[i].second, min_stake);
return false;
}
if (stakes[i].second > remaining) {
LOG_PRINT_L1("Registration tx rejected: stake " << i << " (" << stakes[i].second << ") exceeds available remaining stake (" << remaining << ")");
oxen::log::info(logcat, "Registration tx rejected: stake {} ({}) exceeds available remaining stake ({})", i, stakes[i].second, remaining);
return false;
}

View File

@ -1,9 +1,6 @@
#include "service_node_swarm.h"
#include "common/random.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "service_nodes"
#ifdef UNIT_TEST
#define prod_static
#else
@ -12,6 +9,8 @@
namespace service_nodes
{
static auto logcat = oxen::log::Cat("service_nodes");
uint64_t get_new_swarm_id(const swarm_snode_map_t &swarm_to_snodes)
{
if (swarm_to_snodes.empty()) return 0;
@ -70,7 +69,7 @@ namespace service_nodes
const ssize_t margin = pair.second.size() - EXCESS_BASE;
return result + std::max(margin, ssize_t(0));
});
LOG_PRINT_L2("Calculated excess: " << excess);
oxen::log::debug(logcat, "Calculated excess: {}", excess);
return excess;
};
@ -81,7 +80,7 @@ namespace service_nodes
prod_static size_t calc_threshold(const swarm_snode_map_t &swarm_to_snodes)
{
const size_t threshold = NEW_SWARM_SIZE + (swarm_to_snodes.size() * IDEAL_SWARM_MARGIN);
LOG_PRINT_L2("Calculated threshold: " << threshold);
oxen::log::debug(logcat, "Calculated threshold: {}", threshold);
return threshold;
};
@ -137,7 +136,7 @@ namespace service_nodes
while (calc_excess(swarm_to_snodes) >= calc_threshold(swarm_to_snodes))
{
LOG_PRINT_L2("New swarm creation");
oxen::log::debug(logcat, "New swarm creation");
std::vector<crypto::public_key> new_swarm_snodes;
new_swarm_snodes.reserve(NEW_SWARM_SIZE);
while (new_swarm_snodes.size() < NEW_SWARM_SIZE)
@ -146,7 +145,7 @@ namespace service_nodes
get_excess_pool(EXCESS_BASE, swarm_to_snodes, pool_snodes, excess);
if (pool_snodes.size() == 0)
{
MERROR("Error while getting excess pool for new swarm creation");
oxen::log::error(logcat, "Error while getting excess pool for new swarm creation");
return;
}
const auto& random_excess_snode = pick_from_excess_pool(pool_snodes, mt);
@ -156,12 +155,12 @@ namespace service_nodes
const auto new_swarm_id = get_new_swarm_id(swarm_to_snodes);
if (auto [it, ins] = swarm_to_snodes.emplace(new_swarm_id, std::move(new_swarm_snodes));
!ins) {
MFATAL("New swarm ID gave a swarm id (" << new_swarm_id << ") that already exists -- this is a bug!");
oxen::log::error(logcat, "New swarm ID gave a swarm id ({}) that already exists -- this is a bug!", new_swarm_id);
// If we actually abort() here then hitting this would potentially kill the whole network
// if we hit this bug, so just warn very loudly and move on; if it happens we'll have to
// track down the bug and fix it separately.
} else {
LOG_PRINT_L2("Created new swarm from excess: " << new_swarm_id);
oxen::log::debug(logcat, "Created new swarm from excess: {}", new_swarm_id);
}
}
}
@ -228,22 +227,22 @@ namespace service_nodes
swarm_to_snodes.erase(it);
}
LOG_PRINT_L3("calc_swarm_changes. swarms: " << swarm_to_snodes.size() << ", regs: " << unassigned_snodes.size());
oxen::log::trace(logcat, "calc_swarm_changes. swarms: {}, regs: {}", swarm_to_snodes.size(), unassigned_snodes.size());
/// 0. Ensure there is always 1 swarm
if (swarm_to_snodes.size() == 0)
{
const auto new_swarm_id = get_new_swarm_id({});
swarm_to_snodes.insert({new_swarm_id, {}});
LOG_PRINT_L2("Created initial swarm " << new_swarm_id);
oxen::log::debug(logcat, "Created initial swarm {}", new_swarm_id);
}
/// 1. Assign new registered snodes
assign_snodes(unassigned_snodes, swarm_to_snodes, mersenne_twister, FILL_SWARM_LOWER_PERCENTILE);
LOG_PRINT_L2("After assignment:");
oxen::log::debug(logcat, "After assignment:");
for (const auto &entry : swarm_to_snodes)
{
LOG_PRINT_L2(entry.first << ": " << entry.second.size());
oxen::log::debug(logcat, "{}: {}", entry.first, entry.second.size());
}
/// 2. *Robin Hood Round* steal snodes from wealthy swarms and give them to the poor
@ -276,7 +275,7 @@ namespace service_nodes
remove_excess_snode_from_swarm(excess_snode, swarm_to_snodes);
/// Add public key to poor swarm
poor_swarm_snodes.push_back(excess_snode.public_key);
LOG_PRINT_L2("Stolen 1 snode from " << excess_snode.public_key << " and donated to " << swarm.swarm_id);
oxen::log::debug(logcat, "Stolen 1 snode from {} and donated to {}", excess_snode.public_key, swarm.swarm_id);
} while (poor_swarm_snodes.size() < MIN_SWARM_SIZE);
/// If there is not enough excess for the current swarm,
@ -302,7 +301,7 @@ namespace service_nodes
if (it == swarm_to_snodes.end())
break;
MWARNING("swarm " << it->first << " is DECOMMISSIONED");
oxen::log::warning(logcat, "swarm {} is DECOMMISSIONED", it->first);
/// Good ol' switcheroo
std::vector<crypto::public_key> decommissioned_snodes;
std::swap(decommissioned_snodes, it->second);
@ -314,10 +313,10 @@ namespace service_nodes
}
/// print
LOG_PRINT_L2("Swarm outputs:");
oxen::log::debug(logcat, "Swarm outputs:");
for (const auto &entry : swarm_to_snodes)
{
LOG_PRINT_L2(entry.first << ": " << entry.second.size());
oxen::log::debug(logcat, "{}: {}", entry.first, entry.second.size());
}
}
}

View File

@ -43,13 +43,12 @@
#include <string>
#include <vector>
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "service_nodes"
using cryptonote::hf;
namespace service_nodes
{
static auto logcat = oxen::log::Cat("service_nodes");
static crypto::hash make_state_change_vote_hash(uint64_t block_height, uint32_t service_node_index, new_state state)
{
uint16_t state_int = static_cast<uint16_t>(state);
@ -72,7 +71,7 @@ namespace service_nodes
{
default:
{
LOG_PRINT_L1("Unhandled vote type with value: " << (int)vote.type);
oxen::log::info(logcat, "Unhandled vote type with value: {}", (int)vote.type);
assert("Unhandled vote type" == 0);
return result;
};
@ -108,7 +107,7 @@ namespace service_nodes
if (worker_index >= quorum.workers.size())
{
if (vvc) vvc->m_worker_index_out_of_bounds = true;
LOG_PRINT_L1("Quorum worker index in was out of bounds: " << worker_index << ", expected to be in range of: [0, " << quorum.workers.size() << ")");
oxen::log::info(logcat, "Quorum worker index in was out of bounds: {}, expected to be in range of: [0, {}", worker_index, quorum.workers.size());
return false;
}
return true;
@ -119,7 +118,7 @@ namespace service_nodes
if (validator_index >= quorum.validators.size())
{
if (vvc) vvc->m_validator_index_out_of_bounds = true;
LOG_PRINT_L1("Validator's index was out of bounds: " << validator_index << ", expected to be in range of: [0, " << quorum.validators.size() << ")");
oxen::log::info(logcat, "Validator's index was out of bounds: {}, expected to be in range of: [0, {}", validator_index, quorum.validators.size());
return false;
}
return true;
@ -139,26 +138,26 @@ namespace service_nodes
auto &vvc = tvc.m_vote_ctx;
if (state_change.state != new_state::deregister && hf_version < hf::hf12_checkpointing)
{
LOG_PRINT_L1("Non-deregister state changes are invalid before v12");
oxen::log::info(logcat, "Non-deregister state changes are invalid before v12");
return bad_tx(tvc);
}
if (state_change.state >= new_state::_count)
{
LOG_PRINT_L1("Unknown state change to new state: " << static_cast<uint16_t>(state_change.state));
oxen::log::info(logcat, "Unknown state change to new state: {}", static_cast<uint16_t>(state_change.state));
return bad_tx(tvc);
}
if (state_change.votes.size() < service_nodes::STATE_CHANGE_MIN_VOTES_TO_CHANGE_STATE)
{
LOG_PRINT_L1("Not enough votes");
oxen::log::info(logcat, "Not enough votes");
vvc.m_not_enough_votes = true;
return bad_tx(tvc);
}
if (state_change.votes.size() > service_nodes::STATE_CHANGE_QUORUM_SIZE)
{
LOG_PRINT_L1("Too many votes");
oxen::log::info(logcat, "Too many votes");
return bad_tx(tvc);
}
@ -169,10 +168,7 @@ namespace service_nodes
{
if (state_change.block_height >= latest_height)
{
LOG_PRINT_L1("Received state change tx for height: " << state_change.block_height
<< " and service node: " << state_change.service_node_index
<< ", is newer than current height: " << latest_height
<< " blocks and has been rejected.");
oxen::log::info(logcat, "Received state change tx for height: {} and service node: {}, is newer than current height: {} blocks and has been rejected.", state_change.block_height, state_change.service_node_index, latest_height);
vvc.m_invalid_block_height = true;
if (state_change.block_height >= latest_height + VOTE_OR_TX_VERIFY_HEIGHT_BUFFER)
tvc.m_verifivation_failed = true;
@ -181,11 +177,7 @@ namespace service_nodes
if (latest_height >= state_change.block_height + service_nodes::STATE_CHANGE_TX_LIFETIME_IN_BLOCKS)
{
LOG_PRINT_L1("Received state change tx for height: "
<< state_change.block_height << " and service node: " << state_change.service_node_index
<< ", is older than: " << service_nodes::STATE_CHANGE_TX_LIFETIME_IN_BLOCKS
<< " (current height: " << latest_height << ") "
<< "blocks and has been rejected.");
oxen::log::info(logcat, "Received state change tx for height: {} and service node: {}, is older than: {} (current height: {}) blocks and has been rejected.", state_change.block_height, state_change.service_node_index, service_nodes::STATE_CHANGE_TX_LIFETIME_IN_BLOCKS, latest_height);
vvc.m_invalid_block_height = true;
if (latest_height >= state_change.block_height + (service_nodes::STATE_CHANGE_TX_LIFETIME_IN_BLOCKS + VOTE_OR_TX_VERIFY_HEIGHT_BUFFER))
tvc.m_verifivation_failed = true;
@ -203,8 +195,7 @@ namespace service_nodes
if (validator_index_tracker >= static_cast<int>(vote.validator_index))
{
vvc.m_votes_not_sorted = true;
LOG_PRINT_L1("Vote validator index is not stored in ascending order, prev validator index: "
<< validator_index_tracker << ", curr index: " << vote.validator_index);
oxen::log::info(logcat, "Vote validator index is not stored in ascending order, prev validator index: {}, curr index: {}", validator_index_tracker, vote.validator_index);
return bad_tx(tvc);
}
validator_index_tracker = vote.validator_index;
@ -216,14 +207,14 @@ namespace service_nodes
if (++validator_set[vote.validator_index] > 1)
{
vvc.m_duplicate_voters = true;
LOG_PRINT_L1("Voter quorum index is duplicated: " << vote.validator_index);
oxen::log::info(logcat, "Voter quorum index is duplicated: {}", vote.validator_index);
return bad_tx(tvc);
}
crypto::public_key const &key = quorum.validators[vote.validator_index];
if (!crypto::check_signature(hash, key, vote.signature))
{
LOG_PRINT_L1("Invalid signature for voter " << vote.validator_index << "/" << key);
oxen::log::info(logcat, "Invalid signature for voter {}/{}", vote.validator_index, key);
vvc.m_signature_not_valid = true;
return bad_tx(tvc);
}
@ -250,13 +241,13 @@ namespace service_nodes
{
if (signatures.size() < service_nodes::CHECKPOINT_MIN_VOTES)
{
MGINFO("Checkpoint has insufficient signatures to be considered at height: " << height);
oxen::log::info(logcat, "Checkpoint has insufficient signatures to be considered at height: {}", height);
return false;
}
if (signatures.size() > service_nodes::CHECKPOINT_QUORUM_SIZE)
{
MGINFO("Checkpoint has too many signatures to be considered at height: " << height);
oxen::log::info(logcat, "Checkpoint has too many signatures to be considered at height: {}", height);
return false;
}
@ -268,13 +259,13 @@ namespace service_nodes
{
if (signatures.size() != PULSE_BLOCK_REQUIRED_SIGNATURES)
{
MGINFO("Pulse block has " << signatures.size() << " signatures but requires " << PULSE_BLOCK_REQUIRED_SIGNATURES);
oxen::log::info(logcat, "Pulse block has {} signatures but requires {}", signatures.size(), PULSE_BLOCK_REQUIRED_SIGNATURES);
return false;
}
if (!block)
{
MGINFO("Internal Error: Wrong type passed in any object, expected block.");
oxen::log::info(logcat, "Internal Error: Wrong type passed in any object, expected block.");
return false;
}
@ -282,7 +273,7 @@ namespace service_nodes
{
auto mask = std::bitset<sizeof(pulse_validator_bit_mask()) * 8>(pulse_validator_bit_mask());
auto other = std::bitset<sizeof(pulse_validator_bit_mask()) * 8>(block->pulse.validator_bitset);
MGINFO("Pulse block specifies validator participation bits out of bounds. Expected the bit mask: " << mask << ", block: " << other);
oxen::log::info(logcat, "Pulse block specifies validator participation bits out of bounds. Expected the bit mask: {}, block: {}", mask.to_string(), other.to_string());
return false;
}
}
@ -299,7 +290,7 @@ namespace service_nodes
if (curr >= next)
{
MGINFO("Voters in signatures are not given in ascending order, failed verification at height: " << height);
oxen::log::info(logcat, "Voters in signatures are not given in ascending order, failed verification at height: {}", height);
return false;
}
}
@ -311,14 +302,14 @@ namespace service_nodes
{
if (!block)
{
MGINFO("Internal Error: Wrong type passed in any object, expected block.");
oxen::log::info(logcat, "Internal Error: Wrong type passed in any object, expected block.");
return false;
}
uint16_t bit = 1 << quorum_signature.voter_index;
if ((block->pulse.validator_bitset & bit) == 0)
{
MGINFO("Received pulse signature from validator " << static_cast<int>(quorum_signature.voter_index) << " that is not participating in round " << static_cast<int>(block->pulse.round));
oxen::log::info(logcat, "Received pulse signature from validator {} that is not participating in round {}", static_cast<int>(quorum_signature.voter_index), static_cast<int>(block->pulse.round));
return false;
}
}
@ -326,19 +317,19 @@ namespace service_nodes
crypto::public_key const &key = quorum.validators[quorum_signature.voter_index];
if (quorum_signature.voter_index >= unique_vote_set.size())
{
MGINFO("Internal Error: Voter Index indexes out of bounds of the vote set, index: " << quorum_signature.voter_index << "vote set size: " << unique_vote_set.size());
oxen::log::info(logcat, "Internal Error: Voter Index indexes out of bounds of the vote set, index: {}vote set size: {}", quorum_signature.voter_index, unique_vote_set.size());
return false;
}
if (unique_vote_set[quorum_signature.voter_index]++)
{
MGINFO("Voter: " << tools::type_to_hex(key) << ", quorum index is duplicated: " << quorum_signature.voter_index << ", failed verification at height: " << height);
oxen::log::info(logcat, "Voter: {}, quorum index is duplicated: {}, failed verification at height: {}", tools::type_to_hex(key), quorum_signature.voter_index, height);
return false;
}
if (!crypto::check_signature(hash, key, quorum_signature.signature))
{
MGINFO("Incorrect signature for vote, failed verification at height: " << height << " for voter: " << key << "\n" << quorum);
oxen::log::info(logcat, "Incorrect signature for vote, failed verification at height: {} for voter: {}\n{}", height, key, quorum);
return false;
}
}
@ -358,13 +349,13 @@ namespace service_nodes
{
if ((checkpoint.height % service_nodes::CHECKPOINT_INTERVAL) != 0)
{
LOG_PRINT_L1("Checkpoint given but not expecting a checkpoint at height: " << checkpoint.height);
oxen::log::info(logcat, "Checkpoint given but not expecting a checkpoint at height: {}", checkpoint.height);
return false;
}
if (!verify_quorum_signatures(quorum, quorum_type::checkpointing, hf_version, checkpoint.height, checkpoint.block_hash, checkpoint.signatures))
{
LOG_PRINT_L1("Checkpoint failed signature validation at block " << checkpoint.height << " " << checkpoint.block_hash);
oxen::log::info(logcat, "Checkpoint failed signature validation at block {} {}", checkpoint.height, checkpoint.block_hash);
return false;
}
}
@ -372,7 +363,7 @@ namespace service_nodes
{
if (checkpoint.signatures.size() != 0)
{
LOG_PRINT_L1("Non service-node checkpoints should have no signatures, checkpoint failed at height: " << checkpoint.height);
oxen::log::info(logcat, "Non service-node checkpoints should have no signatures, checkpoint failed at height: {}", checkpoint.height);
return false;
}
}
@ -422,15 +413,13 @@ namespace service_nodes
if (latest_height > vote.block_height + VOTE_LIFETIME)
{
height_in_buffer = latest_height <= vote.block_height + (VOTE_LIFETIME + VOTE_OR_TX_VERIFY_HEIGHT_BUFFER);
LOG_PRINT_L1("Received vote for height: " << vote.block_height << ", is older than: " << VOTE_LIFETIME
<< " blocks and has been rejected.");
oxen::log::info(logcat, "Received vote for height: {}, is older than: {} blocks and has been rejected.", vote.block_height, VOTE_LIFETIME);
vvc.m_invalid_block_height = true;
}
else if (vote.block_height > latest_height)
{
height_in_buffer = vote.block_height <= latest_height + VOTE_OR_TX_VERIFY_HEIGHT_BUFFER;
LOG_PRINT_L1("Received vote for height: " << vote.block_height << ", is newer than: " << latest_height
<< " (latest block height) and has been rejected.");
oxen::log::info(logcat, "Received vote for height: {}, is newer than: {} (latest block height) and has been rejected.", vote.block_height, latest_height);
vvc.m_invalid_block_height = true;
}
@ -476,7 +465,7 @@ namespace service_nodes
{
default:
{
LOG_PRINT_L1("Unhandled vote type with value: " << (int)vote.type);
oxen::log::info(logcat, "Unhandled vote type with value: {}", (int)vote.type);
assert("Unhandled vote type" == 0);
return false;
};
@ -485,7 +474,7 @@ namespace service_nodes
{
if (vote.group != quorum_group::validator)
{
LOG_PRINT_L1("Vote received specifies incorrect voting group, expected vote from validator");
oxen::log::info(logcat, "Vote received specifies incorrect voting group, expected vote from validator");
vvc.m_incorrect_voting_group = true;
result = false;
}
@ -502,7 +491,7 @@ namespace service_nodes
{
if (vote.group != quorum_group::validator)
{
LOG_PRINT_L1("Vote received specifies incorrect voting group");
oxen::log::info(logcat, "Vote received specifies incorrect voting group");
vvc.m_incorrect_voting_group = true;
result = false;
}
@ -520,9 +509,7 @@ namespace service_nodes
result = crypto::check_signature(hash, key, vote.signature);
if (result)
MDEBUG("Signature accepted for " << vote.type << " voter " << vote.index_in_group << "/" << key
<< (vote.type == quorum_type::obligations ? " voting for worker " + std::to_string(vote.state_change.worker_index) : "")
<< " at height " << vote.block_height);
oxen::log::debug(logcat, "Signature accepted for {} voter {}/{} voting for worker {} at height {}", vote.type, vote.index_in_group, key, (vote.type == quorum_type::obligations ? " voting for worker " + std::to_string(vote.state_change.worker_index) : ""), vote.block_height);
else
vvc.m_signature_not_valid = true;
@ -545,7 +532,7 @@ namespace service_nodes
switch(find_vote.type)
{
default:
LOG_PRINT_L1("Unhandled find_vote type with value: " << (int)find_vote.type);
oxen::log::info(logcat, "Unhandled find_vote type with value: {}", (int)find_vote.type);
assert("Unhandled find_vote type" == 0);
return nullptr;
@ -656,7 +643,7 @@ namespace service_nodes
cryptonote::tx_extra_service_node_state_change state_change;
if (!get_service_node_state_change_from_tx_extra(tx.extra, state_change, version))
{
LOG_ERROR("Could not get state change from tx, possibly corrupt tx");
oxen::log::error(logcat, "Could not get state change from tx, possibly corrupt tx");
continue;
}

View File

@ -63,15 +63,20 @@ namespace service_nodes
_count
};
inline std::ostream &operator<<(std::ostream &os, quorum_type v) {
switch(v)
inline std::string to_string(const quorum_type& q)
{
switch(q)
{
case quorum_type::obligations: return os << "obligation";
case quorum_type::checkpointing: return os << "checkpointing";
case quorum_type::blink: return os << "blink";
case quorum_type::pulse: return os << "pulse";
default: assert(false); return os << "xx_unhandled_type";
case quorum_type::obligations: return "obligation";
case quorum_type::checkpointing: return "checkpointing";
case quorum_type::blink: return "blink";
case quorum_type::pulse: return "pulse";
default: assert(false); return "xx_unhandled_type";
}
};
inline std::ostream &operator<<(std::ostream &os, quorum_type q) {
return os << to_string(q);
}
enum struct quorum_group : uint8_t { invalid, validator, worker, _count };
@ -171,4 +176,12 @@ namespace service_nodes
mutable std::recursive_mutex m_lock;
};
}; // namespace service_nodes
//
template <>
struct fmt::formatter<service_nodes::quorum_type> : fmt::formatter<std::string> {
auto format(service_nodes::quorum_type quorum, format_context& ctx) {
return formatter<std::string>::format(
fmt::format("{}", to_string(quorum)), ctx);
}
};

View File

@ -50,7 +50,7 @@ crypto::public_key blink_tx::get_sn_pubkey(subquorum q, int position, const serv
if (!blink_quorum) {
// TODO FIXME XXX - we don't want a failure here; if this happens we need to go back into state
// history to retrieve the state info. (Or maybe this can't happen?)
MERROR("FIXME: could not get blink quorum for blink_tx");
oxen::log::error(globallogcat, "FIXME: could not get blink quorum for blink_tx");
return crypto::null_pkey;
}

View File

@ -48,18 +48,17 @@
#include "common/median.h"
#include "epee/int-util.h"
#include "epee/warnings.h"
#include "common/perf_timer.h"
#include "crypto/hash.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "txpool"
DISABLE_VS_WARNINGS(4244 4345 4503) //'boost::foreach_detail_::or_' : decorated name length exceeded, name was truncated
using namespace crypto;
namespace cryptonote
{
static auto logcat = oxen::log::Cat("txpool");
namespace
{
//TODO: constants such as these should at least be in the header,
@ -104,7 +103,7 @@ namespace cryptonote
tx_extra_service_node_state_change state_change;
if (!get_service_node_state_change_from_tx_extra(tx.extra, state_change, hard_fork_version))
{
MERROR("Could not get service node state change from tx: " << get_transaction_hash(tx) << ", possibly corrupt tx in your blockchain, rejecting malformed state change");
oxen::log::error(logcat, "Could not get service node state change from tx: {}, possibly corrupt tx in your blockchain, rejecting malformed state change", get_transaction_hash(tx));
return false;
}
@ -129,7 +128,7 @@ namespace cryptonote
tx_extra_service_node_state_change pool_tx_state_change;
if (!get_service_node_state_change_from_tx_extra(pool_tx.extra, pool_tx_state_change, hard_fork_version))
{
LOG_PRINT_L1("Could not get service node state change from tx: " << get_transaction_hash(pool_tx) << ", possibly corrupt tx in the pool");
oxen::log::info(logcat, "Could not get service node state change from tx: {}, possibly corrupt tx in the pool", get_transaction_hash(pool_tx));
continue;
}
@ -161,7 +160,7 @@ namespace cryptonote
tx_extra_tx_key_image_unlock unlock;
if (!cryptonote::get_field_from_tx_extra(tx.extra, unlock))
{
MERROR("Could not get key image unlock from tx: " << get_transaction_hash(tx) << ", tx to add is possibly invalid, rejecting");
oxen::log::error(logcat, "Could not get key image unlock from tx: {}, tx to add is possibly invalid, rejecting", get_transaction_hash(tx));
return true;
}
@ -175,13 +174,13 @@ namespace cryptonote
tx_extra_tx_key_image_unlock pool_unlock;
if (!cryptonote::get_field_from_tx_extra(pool_tx.extra, pool_unlock))
{
LOG_PRINT_L1("Could not get key image unlock from tx: " << get_transaction_hash(tx) << ", possibly corrupt tx in the pool");
oxen::log::info(logcat, "Could not get key image unlock from tx: {}, possibly corrupt tx in the pool", get_transaction_hash(tx));
return true;
}
if (unlock == pool_unlock)
{
LOG_PRINT_L1("New TX: " << get_transaction_hash(tx) << ", has TX: " << get_transaction_hash(pool_tx) << " from the pool that is requesting to unlock the same key image already.");
oxen::log::info(logcat, "New TX: {}, has TX: {} from the pool that is requesting to unlock the same key image already.", get_transaction_hash(tx), get_transaction_hash(pool_tx));
return true;
}
}
@ -192,7 +191,7 @@ namespace cryptonote
tx_extra_oxen_name_system data;
if (!cryptonote::get_field_from_tx_extra(tx.extra, data))
{
MERROR("Could not get acquire name service from tx: " << get_transaction_hash(tx) << ", tx to add is possibly invalid, rejecting");
oxen::log::error(logcat, "Could not get acquire name service from tx: {}, tx to add is possibly invalid, rejecting", get_transaction_hash(tx));
return true;
}
@ -206,13 +205,13 @@ namespace cryptonote
tx_extra_oxen_name_system pool_data;
if (!cryptonote::get_field_from_tx_extra(pool_tx.extra, pool_data))
{
LOG_PRINT_L1("Could not get acquire name service from tx: " << get_transaction_hash(tx) << ", possibly corrupt tx in the pool");
oxen::log::info(logcat, "Could not get acquire name service from tx: {}, possibly corrupt tx in the pool", get_transaction_hash(tx));
return true;
}
if (data.type == pool_data.type && data.name_hash == pool_data.name_hash)
{
LOG_PRINT_L1("New TX: " << get_transaction_hash(tx) << ", has TX: " << get_transaction_hash(pool_tx) << " from the pool that is requesting the same ONS entry already.");
oxen::log::info(logcat, "New TX: {}, has TX: {} from the pool that is requesting the same ONS entry already.", get_transaction_hash(tx), get_transaction_hash(pool_tx));
return true;
}
}
@ -222,7 +221,7 @@ namespace cryptonote
if (tx.type != txtype::standard && tx.type != txtype::stake)
{
// NOTE(oxen): This is a developer error. If we come across this in production, be conservative and just reject
MERROR("Unrecognised transaction type: " << tx.type << " for tx: " << get_transaction_hash(tx));
oxen::log::error(logcat, "Unrecognised transaction type: {} for tx: {}", tx.type, get_transaction_hash(tx));
return true;
}
}
@ -242,11 +241,10 @@ namespace cryptonote
// this should already be called with that lock, but let's make it explicit for clarity
std::unique_lock lock{m_transactions_lock};
PERF_TIMER(add_tx);
if (tx.version == txversion::v0)
{
// v0 never accepted
LOG_PRINT_L1("transaction version 0 is invalid");
oxen::log::info(logcat, "transaction version 0 is invalid");
tvc.m_verifivation_failed = true;
return false;
}
@ -293,7 +291,7 @@ namespace cryptonote
size_t tx_weight_limit = get_transaction_weight_limit(hf_version);
if ((!opts.kept_by_block || hf_version >= feature::PER_BYTE_FEE) && tx_weight > tx_weight_limit)
{
LOG_PRINT_L1("transaction is too heavy: " << tx_weight << " bytes, maximum weight: " << tx_weight_limit);
oxen::log::info(logcat, "transaction is too heavy: {} bytes, maximum weight: {}", tx_weight, tx_weight_limit);
tvc.m_verifivation_failed = true;
tvc.m_too_big = true;
return false;
@ -317,7 +315,7 @@ namespace cryptonote
if (tx_hash != id && m_blinks.count(tx_hash))
{
// Warn on this because it almost certainly indicates something malicious
MWARNING("Not re-adding popped/incoming tx " << id << " to the mempool: it conflicts with blink tx " << tx_hash);
oxen::log::warning(logcat, "Not re-adding popped/incoming tx {} to the mempool: it conflicts with blink tx {}", id, tx_hash);
double_spend = true;
break;
}
@ -325,17 +323,17 @@ namespace cryptonote
}
else if (opts.approved_blink)
{
MDEBUG("Incoming blink tx is approved, but has " << conflict_txs.size() << " conflicting local tx(es); dropping conflicts");
oxen::log::debug(logcat, "Incoming blink tx is approved, but has {} conflicting local tx(es); dropping conflicts", conflict_txs.size());
if (remove_blink_conflicts(id, conflict_txs, blink_rollback_height))
double_spend = false;
else
MERROR("Blink error: incoming blink tx cannot be accepted as it conflicts with checkpointed txs");
oxen::log::error(logcat, "Blink error: incoming blink tx cannot be accepted as it conflicts with checkpointed txs");
}
if (double_spend)
{
mark_double_spend(tx);
LOG_PRINT_L1("Transaction with id= "<< id << " used already spent key images");
oxen::log::info(logcat, "Transaction with id= {} used already spent key images", id);
tvc.m_verifivation_failed = true;
tvc.m_double_spend = true;
return false;
@ -345,7 +343,7 @@ namespace cryptonote
if (!opts.kept_by_block && have_duplicated_non_standard_tx(tx, hf_version))
{
mark_double_spend(tx);
LOG_PRINT_L1("Transaction with id= "<< id << " already has a duplicate tx for height");
oxen::log::info(logcat, "Transaction with id= {} already has a duplicate tx for height", id);
tvc.m_verifivation_failed = true;
tvc.m_double_spend = true;
return false;
@ -353,7 +351,7 @@ namespace cryptonote
if (!m_blockchain.check_tx_outputs(tx, tvc))
{
LOG_PRINT_L1("Transaction with id= "<< id << " has at least one invalid output");
oxen::log::info(logcat, "Transaction with id= {} has at least one invalid output", id);
tvc.m_verifivation_failed = true;
tvc.m_invalid_output = true;
return false;
@ -403,14 +401,14 @@ namespace cryptonote
}
catch (const std::exception &e)
{
MERROR("Error adding transaction to txpool: " << e.what());
oxen::log::error(logcat, "Error adding transaction to txpool: {}", e.what());
return false;
}
tvc.m_verifivation_impossible = true;
tvc.m_added_to_pool = true;
}else
{
LOG_PRINT_L1("tx used wrong inputs, rejected");
oxen::log::info(logcat, "tx used wrong inputs, rejected");
tvc.m_verifivation_failed = true;
tvc.m_invalid_input = true;
return false;
@ -449,7 +447,7 @@ namespace cryptonote
}
catch (const std::exception &e)
{
MERROR("internal error: error adding transaction to txpool: " << e.what());
oxen::log::error(logcat, "internal error: error adding transaction to txpool: {}", e.what());
return false;
}
tvc.m_added_to_pool = true;
@ -463,7 +461,7 @@ namespace cryptonote
++m_cookie;
MINFO("Transaction added to pool: txid " << id << " weight: " << tx_weight << " fee/byte: " << (fee / (double)(tx_weight ? tx_weight : 1)));
oxen::log::info(logcat, "Transaction added to pool: txid {} weight: {} fee/byte: {}", id, tx_weight, (fee / (double)(tx_weight ? tx_weight : 1)));
if (!opts.kept_by_block && !opts.do_not_relay)
for (auto& notify : m_tx_notify)
@ -651,7 +649,7 @@ namespace cryptonote
{
if (m_blinks.count(tx_hash))
{
MERROR("Blink error: incoming blink tx " << id << " conflicts with another blink tx " << tx_hash);
oxen::log::error(logcat, "Blink error: incoming blink tx {} conflicts with another blink tx {}", id, tx_hash);
return false;
}
}
@ -664,7 +662,7 @@ namespace cryptonote
auto heights = m_blockchain.get_transactions_heights(conflict_txs);
for (size_t i = 0; i < heights.size(); ++i)
{
MDEBUG("Conflicting tx " << conflict_txs[i] << (heights[i] ? "mined at height " + std::to_string(heights[i]) : "in mempool"));
oxen::log::debug(logcat, "Conflicting tx {}{}", conflict_txs[i], (heights[i] ? "mined at height " + std::to_string(heights[i]) : "in mempool"));
if (!heights[i])
{
mempool_txs.push_back(conflict_txs[i]);
@ -684,10 +682,10 @@ namespace cryptonote
LockedTXN txnlock(m_blockchain);
for (auto &tx : mempool_txs)
{
MWARNING("Removing conflicting tx " << tx << " from mempool for incoming blink tx " << id);
oxen::log::warning(logcat, "Removing conflicting tx {} from mempool for incoming blink tx {}", tx, id);
if (!remove_tx(tx))
{
MERROR("Internal error: Unable to clear conflicting tx " << tx << " from mempool for incoming blink tx " << id);
oxen::log::error(logcat, "Internal error: Unable to clear conflicting tx {} from mempool for incoming blink tx {}", tx, id);
return false;
}
}
@ -696,7 +694,7 @@ namespace cryptonote
if (blink_rollback_height && rollback_height_needed < *blink_rollback_height)
{
MINFO("Incoming blink tx requires a rollback to the " << rollback_height_needed << " to un-mine conflicting transactions");
oxen::log::info(logcat, "Incoming blink tx requires a rollback to the {} to un-mine conflicting transactions", rollback_height_needed);
*blink_rollback_height = rollback_height_needed;
}
@ -721,7 +719,7 @@ namespace cryptonote
const auto it = stc_it ? *stc_it : find_tx_in_sorted_container(txid);
if (it == m_txs_by_fee_and_receive_time.end())
{
MERROR("Failed to find tx in txpool sorted list");
oxen::log::error(logcat, "Failed to find tx in txpool sorted list");
return false;
}
@ -729,7 +727,7 @@ namespace cryptonote
cryptonote::transaction_prefix tx;
if (!parse_and_validate_tx_prefix_from_blob(tx_blob, tx))
{
MERROR("Failed to parse tx from txpool");
oxen::log::error(logcat, "Failed to parse tx from txpool");
return false;
}
@ -740,14 +738,14 @@ namespace cryptonote
meta = &lookup_meta;
else
{
MERROR("Failed to find tx in txpool");
oxen::log::error(logcat, "Failed to find tx in txpool");
return false;
}
}
// remove first, in case this throws, so key images aren't removed
const uint64_t tx_fee = std::get<1>(it->first);
MINFO("Removing tx " << txid << " from txpool: weight: " << meta->weight << ", fee/byte: " << tx_fee);
oxen::log::info(logcat, "Removing tx {} from txpool: weight: {}, fee/byte: {}", txid, meta->weight, tx_fee);
m_blockchain.remove_txpool_tx(txid);
m_txpool_weight -= meta->weight;
remove_transaction_keyimages(tx, txid);
@ -774,7 +772,7 @@ namespace cryptonote
txpool_tx_meta_t meta;
if (!m_blockchain.get_txpool_tx_meta(txid, meta))
{
MERROR("Failed to find tx in txpool");
oxen::log::error(logcat, "Failed to find tx in txpool");
return false;
}
auto del_it = forward ? it++ : it--;
@ -794,7 +792,7 @@ namespace cryptonote
}
catch (const std::exception &e)
{
MERROR("Error while pruning txpool: " << e.what());
oxen::log::error(logcat, "Error while pruning txpool: {}", e.what());
return false;
}
};
@ -825,7 +823,7 @@ namespace cryptonote
if (changed)
++m_cookie;
if (m_txpool_weight > m_txpool_max_weight)
MINFO("Pool weight after pruning is still larger than limit: " << m_txpool_weight << "/" << m_txpool_max_weight);
oxen::log::info(logcat, "Pool weight after pruning is still larger than limit: {}/{}", m_txpool_weight, m_txpool_max_weight);
}
//---------------------------------------------------------------------------------
bool tx_memory_pool::insert_key_images(const transaction_prefix &tx, const crypto::hash &id, bool kept_by_block)
@ -898,7 +896,7 @@ namespace cryptonote
txpool_tx_meta_t meta;
if (!m_blockchain.get_txpool_tx_meta(id, meta))
{
MERROR("Failed to find tx in txpool");
oxen::log::error(logcat, "Failed to find tx in txpool");
return false;
}
txblob = m_blockchain.get_txpool_tx_blob(id);
@ -909,7 +907,7 @@ namespace cryptonote
}
else if (!parse_and_validate_tx_from_blob(txblob, tx))
{
MERROR("Failed to parse tx from txpool");
oxen::log::error(logcat, "Failed to parse tx from txpool");
return false;
}
else
@ -930,7 +928,7 @@ namespace cryptonote
}
catch (const std::exception &e)
{
MERROR("Failed to remove tx from txpool: " << e.what());
oxen::log::error(logcat, "Failed to remove tx from txpool: {}", e.what());
return false;
}
@ -973,11 +971,11 @@ namespace cryptonote
if((tx_age > tools::to_seconds(MEMPOOL_TX_LIVETIME) && !meta.kept_by_block) ||
(tx_age > tools::to_seconds(MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME) && meta.kept_by_block) )
{
LOG_PRINT_L1("Tx " << txid << " removed from tx pool due to outdated, age: " << tx_age );
oxen::log::info(logcat, "Tx {} removed from tx pool due to outdated, age: {}", txid, tx_age);
auto sorted_it = find_tx_in_sorted_container(txid);
if (sorted_it == m_txs_by_fee_and_receive_time.end())
{
LOG_PRINT_L1("Removing tx " << txid << " from tx pool, but it was not found in the sorted txs container!");
oxen::log::info(logcat, "Removing tx {} from tx pool, but it was not found in the sorted txs container!", txid);
}
else
{
@ -1001,7 +999,7 @@ namespace cryptonote
cryptonote::transaction_prefix tx;
if (!parse_and_validate_tx_prefix_from_blob(bd, tx))
{
MERROR("Failed to parse tx from txpool");
oxen::log::error(logcat, "Failed to parse tx from txpool");
// continue
}
else
@ -1014,7 +1012,7 @@ namespace cryptonote
}
catch (const std::exception &e)
{
MWARNING("Failed to remove stuck transaction: " << txid);
oxen::log::warning(logcat, "Failed to remove stuck transaction: {}", txid);
// ignore error
}
}
@ -1048,7 +1046,7 @@ namespace cryptonote
cryptonote::transaction tx;
if (!cryptonote::parse_and_validate_tx_from_blob(bd, tx))
{
LOG_PRINT_L1("TX in pool could not be parsed from blob, txid: " << txid);
oxen::log::info(logcat, "TX in pool could not be parsed from blob, txid: {}", txid);
return true;
}
@ -1060,7 +1058,7 @@ namespace cryptonote
crypto::hash max_used_block_id = null_hash;
if (!m_blockchain.check_tx_inputs(tx, max_used_block_height, max_used_block_id, tvc, /*kept_by_block*/ false))
{
LOG_PRINT_L1("TX type: " << tx.type << " considered for relaying failed tx inputs check, txid: " << txid << ", reason: " << print_tx_verification_context(tvc, &tx));
oxen::log::info(logcat, "TX type: {} considered for relaying failed tx inputs check, txid: {}, reason: {}", tx.type, txid, print_tx_verification_context(tvc, &tx));
return true;
}
}
@ -1069,7 +1067,7 @@ namespace cryptonote
}
catch (const std::exception &e)
{
MERROR("Failed to get transaction blob from db");
oxen::log::error(logcat, "Failed to get transaction blob from db");
// ignore error
}
}
@ -1094,7 +1092,7 @@ namespace cryptonote
++updated;
}
} catch (const std::exception &e) {
MERROR("Failed to upate txpool transaction metadata: " << e.what());
oxen::log::error(logcat, "Failed to upate txpool transaction metadata: {}", e.what());
}
}
lock.commit();
@ -1122,7 +1120,7 @@ namespace cryptonote
}
catch (const std::exception &e)
{
MERROR("Failed to update txpool transaction metadata: " << e.what());
oxen::log::error(logcat, "Failed to update txpool transaction metadata: {}", e.what());
// continue
}
}
@ -1144,7 +1142,7 @@ namespace cryptonote
transaction tx;
if (!parse_and_validate_tx_from_blob(*bd, tx))
{
MERROR("Failed to parse tx from txpool");
oxen::log::error(logcat, "Failed to parse tx from txpool");
// continue
return true;
}
@ -1351,14 +1349,14 @@ namespace cryptonote
crypto::hash tx_hash;
if (!get_transaction_hash(pool_tx, tx_hash))
{
MERROR("Failed to get transaction hash from txpool to check if we can prune a state change");
oxen::log::error(logcat, "Failed to get transaction hash from txpool to check if we can prune a state change");
continue;
}
txpool_tx_meta_t meta;
if (!m_blockchain.get_txpool_tx_meta(tx_hash, meta))
{
MERROR("Failed to get tx meta from txpool to check if we can prune a state change");
oxen::log::error(logcat, "Failed to get tx meta from txpool to check if we can prune a state change");
continue;
}
@ -1465,11 +1463,11 @@ namespace cryptonote
{
// Sanity check; if this happens checkpoints are failing and we can't guarantee blinks
// anyway (because the blink quorums are not immutable).
MERROR("Unable to scan for conflicts: blockchain checkpoints are too far back");
oxen::log::error(logcat, "Unable to scan for conflicts: blockchain checkpoints are too far back");
}
else
{
MDEBUG("Found " << key_image_conflicts.size() << " conflicting key images for blink tx " << txid << "; checking to see if we can roll back");
oxen::log::debug(logcat, "Found {} conflicting key images for blink tx {}; checking to see if we can roll back", key_image_conflicts.size(), txid);
// Check all the key images of all the blockchain transactions in blocks since the immutable
// height, and remove any conflicts from the set of conflicts, updating the rollback height
// as we go. If we remove all then rolling back will work, and we can accept the blink,
@ -1493,7 +1491,7 @@ namespace cryptonote
txs.clear();
if (!m_blockchain.get_transactions(block.tx_hashes, txs))
{
MERROR("Unable to get transactions for block " << block.hash);
oxen::log::error(logcat, "Unable to get transactions for block {}", block.hash);
can_fix_with_a_rollback = false;
break;
}
@ -1510,18 +1508,18 @@ namespace cryptonote
end:
if (key_image_conflicts.empty() && earliest < height && earliest > immutable)
{
MDEBUG("Blink admission requires rolling back to height " << earliest);
oxen::log::debug(logcat, "Blink admission requires rolling back to height {}", earliest);
can_fix_with_a_rollback = true;
if (*blink_rollback_height == 0 || *blink_rollback_height > earliest)
*blink_rollback_height = earliest;
}
}
else
MERROR("Failed to retrieve blocks for trying a blink rollback!");
oxen::log::error(logcat, "Failed to retrieve blocks for trying a blink rollback!");
}
if (!can_fix_with_a_rollback)
{
MWARNING("Blink admission of " << txid << " is not possible even with a rollback: found " << key_image_conflicts.size() << " key image conflicts in immutable blocks");
oxen::log::warning(logcat, "Blink admission of {} is not possible even with a rollback: found {} key image conflicts in immutable blocks", txid, key_image_conflicts.size());
ret = false;
tvc.m_double_spend = true;
}
@ -1656,13 +1654,13 @@ end:
txpool_tx_meta_t meta;
if (!m_blockchain.get_txpool_tx_meta(txid, meta))
{
MERROR("Failed to find tx meta in txpool");
oxen::log::error(logcat, "Failed to find tx meta in txpool");
// continue, not fatal
continue;
}
if (!meta.double_spend_seen)
{
MDEBUG("Marking " << txid << " as double spending " << itk.k_image);
oxen::log::debug(logcat, "Marking {} as double spending {}", txid, itk.k_image);
meta.double_spend_seen = true;
changed = true;
try
@ -1671,7 +1669,7 @@ end:
}
catch (const std::exception &e)
{
MERROR("Failed to update tx meta: " << e.what());
oxen::log::error(logcat, "Failed to update tx meta: {}", e.what());
// continue, not fatal
}
}
@ -1699,7 +1697,7 @@ end:
block_reward_parts reward_parts = {};
if (!get_oxen_block_reward(median_weight, total_weight, already_generated_coins, version, reward_parts, block_reward_context))
{
MERROR("Failed to get block reward for empty block");
oxen::log::error(logcat, "Failed to get block reward for empty block");
return false;
}
@ -1709,7 +1707,7 @@ end:
size_t const max_total_weight = 2 * median_weight - COINBASE_BLOB_RESERVED_SIZE;
std::unordered_set<crypto::key_image> k_images;
LOG_PRINT_L2("Filling block template, median weight " << median_weight << ", " << m_txs_by_fee_and_receive_time.size() << " txes in the pool");
oxen::log::debug(logcat, "Filling block template, median weight {}, {} txes in the pool", median_weight, m_txs_by_fee_and_receive_time.size());
LockedTXN lock(m_blockchain);
@ -1721,15 +1719,15 @@ end:
txpool_tx_meta_t meta;
if (!m_blockchain.get_txpool_tx_meta(sorted_it.second, meta))
{
MERROR(" failed to find tx meta");
oxen::log::error(logcat, " failed to find tx meta");
continue;
}
LOG_PRINT_L2("Considering " << sorted_it.second << ", weight " << meta.weight << ", current block weight " << total_weight << "/" << max_total_weight << ", current reward " << print_money(best_reward));
oxen::log::debug(logcat, "Considering {}, weight {}, current block weight {}/{}, current reward {}", sorted_it.second, meta.weight, total_weight, max_total_weight, print_money(best_reward));
// Can not exceed maximum block weight
if (max_total_weight < total_weight + meta.weight)
{
LOG_PRINT_L2(" would exceed maximum block weight");
oxen::log::debug(logcat, " would exceed maximum block weight");
continue;
}
@ -1741,7 +1739,7 @@ end:
block_reward_parts next_reward_parts = {};
if(!get_oxen_block_reward(median_weight, total_weight + meta.weight, already_generated_coins, version, next_reward_parts, next_block_reward_context))
{
LOG_PRINT_L2("Block reward calculation bug");
oxen::log::debug(logcat, "Block reward calculation bug");
return false;
}
@ -1761,7 +1759,7 @@ end:
// If we're getting lower reward tx, don't include this TX
if (next_reward < best_reward)
{
LOG_PRINT_L2(" would decrease reward to " << print_money(next_reward));
oxen::log::debug(logcat, " would decrease reward to {}", print_money(next_reward));
continue;
}
@ -1784,7 +1782,7 @@ end:
}
catch (const std::exception &e)
{
MERROR("Failed to check transaction readiness: " << e.what());
oxen::log::error(logcat, "Failed to check transaction readiness: {}", e.what());
// continue, not fatal
}
if (memcmp(&original_meta, &meta, sizeof(meta)))
@ -1795,18 +1793,18 @@ end:
}
catch (const std::exception &e)
{
MERROR("Failed to update tx meta: " << e.what());
oxen::log::error(logcat, "Failed to update tx meta: {}", e.what());
// continue, not fatal
}
}
if (!ready)
{
LOG_PRINT_L2(" not ready to go");
oxen::log::debug(logcat, " not ready to go");
continue;
}
if (have_key_images(k_images, tx))
{
LOG_PRINT_L2(" key images already seen");
oxen::log::debug(logcat, " key images already seen");
continue;
}
@ -1816,14 +1814,12 @@ end:
net_fee = next_reward_parts.miner_fee;
best_reward = next_reward;
append_key_images(k_images, tx);
LOG_PRINT_L2(" added, new block weight " << total_weight << "/" << max_total_weight << ", reward " << print_money(best_reward));
oxen::log::debug(logcat, " added, new block weight {}/{}, reward {}", total_weight, max_total_weight, print_money(best_reward));
}
lock.commit();
expected_reward = best_reward;
LOG_PRINT_L2("Block template filled with " << bl.tx_hashes.size() << " txes, weight "
<< total_weight << "/" << max_total_weight << ", reward " << print_money(best_reward)
<< " (including " << print_money(net_fee) << " in fees)");
oxen::log::debug(logcat, "Block template filled with {} txes, weight {}/{}, reward {} (including {} in fees)", bl.tx_hashes.size(), total_weight, max_total_weight, print_money(best_reward), print_money(net_fee));
return true;
}
//---------------------------------------------------------------------------------
@ -1838,11 +1834,11 @@ end:
m_blockchain.for_all_txpool_txes([this, &remove, tx_weight_limit](const crypto::hash &txid, const txpool_tx_meta_t &meta, const std::string*) {
m_txpool_weight += meta.weight;
if (meta.weight > tx_weight_limit) {
LOG_PRINT_L1("Transaction " << txid << " is too big (" << meta.weight << " bytes), removing it from pool");
oxen::log::info(logcat, "Transaction {} is too big ({} bytes), removing it from pool", txid, meta.weight);
remove.insert(txid);
}
else if (m_blockchain.have_tx(txid)) {
LOG_PRINT_L1("Transaction " << txid << " is in the blockchain, removing it from pool");
oxen::log::info(logcat, "Transaction {} is in the blockchain, removing it from pool", txid);
remove.insert(txid);
}
return true;
@ -1860,7 +1856,7 @@ end:
cryptonote::transaction tx;
if (!parse_and_validate_tx_from_blob(txblob, tx))
{
MERROR("Failed to parse tx from txpool");
oxen::log::error(logcat, "Failed to parse tx from txpool");
continue;
}
// remove tx from db first
@ -1870,7 +1866,7 @@ end:
auto sorted_it = find_tx_in_sorted_container(txid);
if (sorted_it == m_txs_by_fee_and_receive_time.end())
{
LOG_PRINT_L1("Removing tx " << txid << " from tx pool, but it was not found in the sorted txs container!");
oxen::log::info(logcat, "Removing tx {} from tx pool, but it was not found in the sorted txs container!", txid);
}
else
{
@ -1880,7 +1876,7 @@ end:
}
catch (const std::exception &e)
{
MERROR("Failed to remove invalid tx from pool");
oxen::log::error(logcat, "Failed to remove invalid tx from pool");
// continue
}
}
@ -1912,13 +1908,13 @@ end:
cryptonote::transaction_prefix tx;
if (!parse_and_validate_tx_prefix_from_blob(*bd, tx))
{
MWARNING("Failed to parse tx from txpool, removing");
oxen::log::warning(logcat, "Failed to parse tx from txpool, removing");
remove.push_back(txid);
return true;
}
if (!insert_key_images(tx, txid, meta.kept_by_block))
{
MFATAL("Failed to insert key images from txpool tx");
oxen::log::error(logcat, "Failed to insert key images from txpool tx");
return false;
}
@ -1941,7 +1937,7 @@ end:
}
catch (const std::exception &e)
{
MWARNING("Failed to remove corrupt transaction: " << txid);
oxen::log::warning(logcat, "Failed to remove corrupt transaction: {}", txid);
// ignore error
}
}

View File

@ -34,25 +34,24 @@
#include "blockchain.h"
#include "tx_sanity_check.h"
#undef OXEN_DEFAULT_LOG_CATEGORY
#define OXEN_DEFAULT_LOG_CATEGORY "verify"
namespace cryptonote
{
static auto logcat = oxen::log::Cat("verify");
bool tx_sanity_check(const std::string &tx_blob, uint64_t rct_outs_available)
{
cryptonote::transaction tx;
if (!cryptonote::parse_and_validate_tx_from_blob(tx_blob, tx))
{
MERROR("Failed to parse transaction");
oxen::log::error(logcat, "Failed to parse transaction");
return false;
}
if (cryptonote::is_coinbase(tx))
{
MERROR("Transaction is coinbase");
oxen::log::error(logcat, "Transaction is coinbase");
return false;
}
std::set<uint64_t> rct_indices;
@ -77,7 +76,7 @@ bool tx_sanity_check(const std::set<uint64_t> &rct_indices, size_t n_indices, ui
{
if (n_indices <= 10)
{
MDEBUG("n_indices is only " << n_indices << ", not checking");
oxen::log::debug(logcat, "n_indices is only {}, not checking", n_indices);
return true;
}
@ -86,7 +85,7 @@ bool tx_sanity_check(const std::set<uint64_t> &rct_indices, size_t n_indices, ui
if (rct_indices.size() < n_indices * 8 / 10)
{
MERROR("amount of unique indices is too low (amount of rct indices is " << rct_indices.size() << ", out of total " << n_indices << "indices.");
oxen::log::error(logcat, "amount of unique indices is too low (amount of rct indices is {}, out of total {} indices)", rct_indices.size(), n_indices);
return false;
}
@ -94,7 +93,7 @@ bool tx_sanity_check(const std::set<uint64_t> &rct_indices, size_t n_indices, ui
uint64_t median = tools::median(std::move(offsets));
if (median < rct_outs_available * 6 / 10)
{
MERROR("median offset index is too low (median is " << median << " out of total " << rct_outs_available << "offsets). Transactions should contain a higher fraction of recent outputs.");
oxen::log::error(logcat, "median offset index is too low (median is {} out of total {}offsets). Transactions should contain a higher fraction of recent outputs.", median, rct_outs_available);
return false;
}

Some files were not shown because too many files have changed in this diff Show More