Merge branch 'master' of https://github.com/monero-project/bitmonero
This commit is contained in:
commit
8fc42a21fc
|
@ -1,3 +1,7 @@
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/build
|
/build
|
||||||
/tags
|
/tags
|
||||||
|
|
||||||
|
# vim swap files
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
|
@ -21,6 +21,11 @@ endif()
|
||||||
|
|
||||||
set(STATIC ${MSVC} CACHE BOOL "Link libraries statically")
|
set(STATIC ${MSVC} CACHE BOOL "Link libraries statically")
|
||||||
|
|
||||||
|
if (UNIX AND NOT APPLE)
|
||||||
|
# Note that at the time of this writing the -Wstrict-prototypes flag added below will make this fail
|
||||||
|
find_package(Threads REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(MSVC)
|
if(MSVC)
|
||||||
add_definitions("/bigobj /MP /W3 /GS- /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4345 /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0 /FIinline_c.h /D__SSE4_1__")
|
add_definitions("/bigobj /MP /W3 /GS- /D_CRT_SECURE_NO_WARNINGS /wd4996 /wd4345 /D_WIN32_WINNT=0x0600 /DWIN32_LEAN_AND_MEAN /DGTEST_HAS_TR1_TUPLE=0 /FIinline_c.h /D__SSE4_1__")
|
||||||
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Dinline=__inline")
|
# set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /Dinline=__inline")
|
||||||
|
@ -44,6 +49,11 @@ else()
|
||||||
else()
|
else()
|
||||||
set(WARNINGS "${WARNINGS} -Wlogical-op -Wno-error=maybe-uninitialized")
|
set(WARNINGS "${WARNINGS} -Wlogical-op -Wno-error=maybe-uninitialized")
|
||||||
endif()
|
endif()
|
||||||
|
# Since gcc 4.9 the LTO format is non-standard (slim), so we need the gcc-specific ar and ranlib binaries
|
||||||
|
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND NOT (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 4.9.0))
|
||||||
|
set(CMAKE_AR "gcc-ar")
|
||||||
|
set(CMAKE_RANLIB "gcc-ranlib")
|
||||||
|
endif()
|
||||||
if(MINGW)
|
if(MINGW)
|
||||||
set(WARNINGS "${WARNINGS} -Wno-error=unused-value")
|
set(WARNINGS "${WARNINGS} -Wno-error=unused-value")
|
||||||
set(MINGW_FLAG "-DWIN32_LEAN_AND_MEAN")
|
set(MINGW_FLAG "-DWIN32_LEAN_AND_MEAN")
|
||||||
|
@ -59,8 +69,8 @@ else()
|
||||||
else()
|
else()
|
||||||
set(STATIC_ASSERT_FLAG "-Dstatic_assert=_Static_assert")
|
set(STATIC_ASSERT_FLAG "-Dstatic_assert=_Static_assert")
|
||||||
endif()
|
endif()
|
||||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG}")
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c11 -D_GNU_SOURCE ${MINGW_FLAG} ${STATIC_ASSERT_FLAG} ${WARNINGS} ${C_WARNINGS} ${ARCH_FLAG} -maes")
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG}")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -D_GNU_SOURCE ${MINGW_FLAG} ${WARNINGS} ${CXX_WARNINGS} ${ARCH_FLAG} -maes")
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGTEST_HAS_TR1_TUPLE=0")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGTEST_HAS_TR1_TUPLE=0")
|
||||||
endif()
|
endif()
|
||||||
|
@ -69,7 +79,11 @@ else()
|
||||||
else()
|
else()
|
||||||
set(DEBUG_FLAGS "-g3 -O0")
|
set(DEBUG_FLAGS "-g3 -O0")
|
||||||
endif()
|
endif()
|
||||||
set(RELEASE_FLAGS "-Ofast -DNDEBUG -Wno-unused-variable -flto")
|
set(RELEASE_FLAGS "-Ofast -DNDEBUG -Wno-unused-variable")
|
||||||
|
if(NOT CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
||||||
|
# There is a clang bug that does not allow to compile code that uses AES-NI intrinsics if -flto is enabled
|
||||||
|
set(RELEASE_FLAGS "${RELEASE_FLAGS} -flto")
|
||||||
|
endif()
|
||||||
#if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT MINGW)
|
#if(CMAKE_C_COMPILER_ID STREQUAL "GNU" AND NOT MINGW)
|
||||||
# set(RELEASE_FLAGS "${RELEASE_FLAGS} -fno-fat-lto-objects")
|
# set(RELEASE_FLAGS "${RELEASE_FLAGS} -fno-fat-lto-objects")
|
||||||
#endif()
|
#endif()
|
||||||
|
@ -77,8 +91,8 @@ else()
|
||||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEBUG_FLAGS}")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${DEBUG_FLAGS}")
|
||||||
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${RELEASE_FLAGS}")
|
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${RELEASE_FLAGS}")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${RELEASE_FLAGS}")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${RELEASE_FLAGS}")
|
||||||
if(STATIC)
|
if(STATIC AND NOT APPLE)
|
||||||
set_static_flags()
|
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static-libgcc -static-libstdc++")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -86,7 +100,7 @@ if(STATIC)
|
||||||
set(Boost_USE_STATIC_LIBS ON)
|
set(Boost_USE_STATIC_LIBS ON)
|
||||||
set(Boost_USE_STATIC_RUNTIME ON)
|
set(Boost_USE_STATIC_RUNTIME ON)
|
||||||
endif()
|
endif()
|
||||||
find_package(Boost 1.53 REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization atomic program_options)
|
find_package(Boost 1.53 REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization program_options)
|
||||||
if((${Boost_MAJOR_VERSION} EQUAL 1) AND (${Boost_MINOR_VERSION} EQUAL 54))
|
if((${Boost_MAJOR_VERSION} EQUAL 1) AND (${Boost_MINOR_VERSION} EQUAL 54))
|
||||||
message(SEND_ERROR "Boost version 1.54 is unsupported, more details are available here http://goo.gl/RrCFmA")
|
message(SEND_ERROR "Boost version 1.54 is unsupported, more details are available here http://goo.gl/RrCFmA")
|
||||||
endif()
|
endif()
|
||||||
|
|
16
README
16
README
|
@ -30,3 +30,19 @@ cmake -G "Visual Studio 11 Win64" ..
|
||||||
|
|
||||||
And then do Build.
|
And then do Build.
|
||||||
Good luck!
|
Good luck!
|
||||||
|
|
||||||
|
|
||||||
|
Build documentation (Doxygen) :
|
||||||
|
Pequired Packages:
|
||||||
|
* doxygen
|
||||||
|
* graphviz (optional)
|
||||||
|
|
||||||
|
From root code directory, execute :
|
||||||
|
|
||||||
|
doxygen Doxyfile
|
||||||
|
|
||||||
|
If you have installed *graphviz*, you can also generate in-doc diagrams :
|
||||||
|
|
||||||
|
HAVE_DOT=YES doxygen Doxyfile
|
||||||
|
|
||||||
|
The output will go in **doc/html/**
|
||||||
|
|
|
@ -1,5 +1,19 @@
|
||||||
Bitmonero
|
Bitmonero
|
||||||
|
|
||||||
|
Release notes 0.8.8
|
||||||
|
|
||||||
|
- JSON RPC v2.0 compatibility
|
||||||
|
- JSON RPC over TCP added- Further optimizations
|
||||||
|
- Fixed a bug with checkpoints behavior
|
||||||
|
- UI improvements for daemon
|
||||||
|
- Fixed COIN value (10^12)
|
||||||
|
- Raised minimum fee to 5 * (10^9)
|
||||||
|
- Temporary fix for block reward DoS attack
|
||||||
|
|
||||||
|
Release notes 0.8.7
|
||||||
|
|
||||||
|
- Slow hash optimizations
|
||||||
|
|
||||||
Release notes 0.8.6
|
Release notes 0.8.6
|
||||||
|
|
||||||
- Simplwallet can set extra for transfers
|
- Simplwallet can set extra for transfers
|
||||||
|
@ -21,17 +35,13 @@ Release notes 0.8.4
|
||||||
Release notes 0.8.3
|
Release notes 0.8.3
|
||||||
|
|
||||||
- JSON RPC for wallet
|
- JSON RPC for wallet
|
||||||
- fixed bug with blockchain storing
|
- Fixed bug with blockchain storing
|
||||||
- fixed bug with correct display of transfer's change
|
- Fixed bug with correct display of transfer's change
|
||||||
- bug fix in simple wallet
|
- Bug fix in simple wallet
|
||||||
|
|
||||||
Release notes 0.8.2
|
Release notes 0.8.2
|
||||||
|
|
||||||
- now wallet is still working when daemon stores blockchain and can't serve clients;
|
- Now wallet is still working when daemon stores blockchain and can't serve clients
|
||||||
- no-console option for a daemon;
|
- No-console option for a daemon
|
||||||
- fixed problem with network synchronization;
|
- Fixed problem with network synchronization
|
||||||
- major bug fix in simple wallet.
|
- Major bug fix in simple wallet
|
||||||
|
|
||||||
Release notes 0.8.1
|
|
||||||
|
|
||||||
Bytecoin project is moved to GitHub
|
|
||||||
|
|
|
@ -233,6 +233,7 @@ namespace epee
|
||||||
|
|
||||||
void stop()
|
void stop()
|
||||||
{
|
{
|
||||||
|
m_running = false;
|
||||||
m_stdin_reader.stop();
|
m_stdin_reader.stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,6 +245,10 @@ namespace epee
|
||||||
bool continue_handle = true;
|
bool continue_handle = true;
|
||||||
while(continue_handle)
|
while(continue_handle)
|
||||||
{
|
{
|
||||||
|
if (!m_running)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (!prompt.empty())
|
if (!prompt.empty())
|
||||||
{
|
{
|
||||||
epee::log_space::set_console_color(epee::log_space::console_color_yellow, true);
|
epee::log_space::set_console_color(epee::log_space::console_color_yellow, true);
|
||||||
|
@ -257,9 +262,7 @@ namespace epee
|
||||||
std::string command;
|
std::string command;
|
||||||
if(!m_stdin_reader.get_line(command))
|
if(!m_stdin_reader.get_line(command))
|
||||||
{
|
{
|
||||||
LOG_PRINT("Failed to read line. Stopping...", LOG_LEVEL_0);
|
LOG_PRINT("Failed to read line.", LOG_LEVEL_0);
|
||||||
continue_handle = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
string_tools::trim(command);
|
string_tools::trim(command);
|
||||||
|
|
||||||
|
@ -267,23 +270,6 @@ namespace epee
|
||||||
if(0 == command.compare("exit") || 0 == command.compare("q"))
|
if(0 == command.compare("exit") || 0 == command.compare("q"))
|
||||||
{
|
{
|
||||||
continue_handle = false;
|
continue_handle = false;
|
||||||
}else if (!command.compare(0, 7, "set_log"))
|
|
||||||
{
|
|
||||||
//parse set_log command
|
|
||||||
if(command.size() != 9)
|
|
||||||
{
|
|
||||||
std::cout << "wrong syntax: " << command << std::endl << "use set_log n" << std::endl;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
uint16_t n = 0;
|
|
||||||
if(!string_tools::get_xtype_from_string(n, command.substr(8, 1)))
|
|
||||||
{
|
|
||||||
std::cout << "wrong syntax: " << command << std::endl << "use set_log n" << std::endl;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
log_space::get_set_log_detalisation_level(true, n);
|
|
||||||
std::cout << "New log level set " << n;
|
|
||||||
LOG_PRINT_L2("New log level set " << n);
|
|
||||||
}else if (command.empty())
|
}else if (command.empty())
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
|
@ -304,6 +290,7 @@ namespace epee
|
||||||
|
|
||||||
private:
|
private:
|
||||||
async_stdin_reader m_stdin_reader;
|
async_stdin_reader m_stdin_reader;
|
||||||
|
bool m_running = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -52,11 +52,11 @@ PRAGMA_WARNING_DISABLE_VS(4355)
|
||||||
typename t_protocol_handler::config_type& config, volatile uint32_t& sock_count, i_connection_filter* &pfilter)
|
typename t_protocol_handler::config_type& config, volatile uint32_t& sock_count, i_connection_filter* &pfilter)
|
||||||
: strand_(io_service),
|
: strand_(io_service),
|
||||||
socket_(io_service),
|
socket_(io_service),
|
||||||
m_protocol_handler(this, config, context),
|
|
||||||
m_want_close_connection(0),
|
m_want_close_connection(0),
|
||||||
m_was_shutdown(0),
|
m_was_shutdown(0),
|
||||||
m_ref_sockets_count(sock_count),
|
m_ref_sockets_count(sock_count),
|
||||||
m_pfilter(pfilter)
|
m_pfilter(pfilter),
|
||||||
|
m_protocol_handler(this, config, context)
|
||||||
{
|
{
|
||||||
boost::interprocess::ipcdetail::atomic_inc32(&m_ref_sockets_count);
|
boost::interprocess::ipcdetail::atomic_inc32(&m_ref_sockets_count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,20 +55,20 @@ namespace net_utils
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
template<class t_connection_context = net_utils::connection_context_base>
|
template<class t_connection_context = net_utils::connection_context_base>
|
||||||
class simple_http_connection_handler
|
class simple_http_connection_handler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef t_connection_context connection_context;//t_connection_context net_utils::connection_context_base connection_context;
|
typedef t_connection_context connection_context;//t_connection_context net_utils::connection_context_base connection_context;
|
||||||
typedef http_server_config config_type;
|
typedef http_server_config config_type;
|
||||||
|
|
||||||
simple_http_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config);
|
simple_http_connection_handler(i_service_endpoint* psnd_hndlr, config_type& config);
|
||||||
virtual ~simple_http_connection_handler(){}
|
virtual ~simple_http_connection_handler(){}
|
||||||
|
|
||||||
bool release_protocol()
|
bool release_protocol()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool thread_init()
|
virtual bool thread_init()
|
||||||
{
|
{
|
||||||
|
@ -86,10 +86,6 @@ namespace net_utils
|
||||||
virtual bool handle_recv(const void* ptr, size_t cb);
|
virtual bool handle_recv(const void* ptr, size_t cb);
|
||||||
virtual bool handle_request(const http::http_request_info& query_info, http_response_info& response);
|
virtual bool handle_request(const http::http_request_info& query_info, http_response_info& response);
|
||||||
|
|
||||||
|
|
||||||
//temporary here
|
|
||||||
//bool parse_uri(const std::string uri, uri_content& content);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum machine_state{
|
enum machine_state{
|
||||||
http_state_retriving_comand_line,
|
http_state_retriving_comand_line,
|
||||||
|
@ -142,34 +138,37 @@ namespace net_utils
|
||||||
i_service_endpoint* m_psnd_hndlr;
|
i_service_endpoint* m_psnd_hndlr;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class t_connection_context>
|
template<class t_connection_context>
|
||||||
struct i_http_server_handler
|
struct i_http_server_handler
|
||||||
{
|
{
|
||||||
virtual ~i_http_server_handler(){}
|
virtual ~i_http_server_handler(){}
|
||||||
virtual bool handle_http_request(const http_request_info& query_info, http_response_info& response, t_connection_context& m_conn_context)=0;
|
virtual bool handle_http_request(const http_request_info& query_info,
|
||||||
virtual bool init_server_thread(){return true;}
|
http_response_info& response,
|
||||||
|
t_connection_context& m_conn_context) = 0;
|
||||||
|
virtual bool init_server_thread(){return true;}
|
||||||
virtual bool deinit_server_thread(){return true;}
|
virtual bool deinit_server_thread(){return true;}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class t_connection_context>
|
template<class t_connection_context>
|
||||||
struct custum_handler_config: public http_server_config
|
struct custum_handler_config: public http_server_config
|
||||||
{
|
{
|
||||||
i_http_server_handler<t_connection_context>* m_phandler;
|
i_http_server_handler<t_connection_context>* m_phandler;
|
||||||
};
|
};
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
|
||||||
template<class t_connection_context = net_utils::connection_context_base>
|
template<class t_connection_context = net_utils::connection_context_base>
|
||||||
class http_custom_handler: public simple_http_connection_handler<t_connection_context>
|
class http_custom_handler: public simple_http_connection_handler<t_connection_context>
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef custum_handler_config<t_connection_context> config_type;
|
typedef custum_handler_config<t_connection_context> config_type;
|
||||||
|
|
||||||
http_custom_handler(i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context):simple_http_connection_handler<t_connection_context>(psnd_hndlr, config),
|
http_custom_handler(i_service_endpoint* psnd_hndlr, config_type& config, t_connection_context& conn_context)
|
||||||
m_config(config),
|
: simple_http_connection_handler<t_connection_context>(psnd_hndlr, config),
|
||||||
m_conn_context(conn_context)
|
m_config(config),
|
||||||
|
m_conn_context(conn_context)
|
||||||
{}
|
{}
|
||||||
inline bool handle_request(const http_request_info& query_info, http_response_info& response)
|
inline bool handle_request(const http_request_info& query_info, http_response_info& response)
|
||||||
{
|
{
|
||||||
|
@ -191,8 +190,8 @@ namespace net_utils
|
||||||
{
|
{
|
||||||
return m_config.m_phandler->deinit_server_thread();
|
return m_config.m_phandler->deinit_server_thread();
|
||||||
}
|
}
|
||||||
void handle_qued_callback()
|
void handle_qued_callback()
|
||||||
{}
|
{}
|
||||||
bool after_init_connection()
|
bool after_init_connection()
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -26,9 +26,10 @@
|
||||||
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "serialization/keyvalue_serialization.h"
|
|
||||||
#include "storages/portable_storage_template_helper.h"
|
|
||||||
#include "http_base.h"
|
#include "http_base.h"
|
||||||
|
#include "jsonrpc_structs.h"
|
||||||
|
#include "storages/portable_storage.h"
|
||||||
|
#include "storages/portable_storage_template_helper.h"
|
||||||
|
|
||||||
|
|
||||||
#define CHAIN_HTTP_TO_MAP2(context_type) bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, \
|
#define CHAIN_HTTP_TO_MAP2(context_type) bool handle_http_request(const epee::net_utils::http::http_request_info& query_info, \
|
||||||
|
@ -109,98 +110,6 @@
|
||||||
#define END_URI_MAP2() return handled;}
|
#define END_URI_MAP2() return handled;}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace epee
|
|
||||||
{
|
|
||||||
namespace json_rpc
|
|
||||||
{
|
|
||||||
template<typename t_param>
|
|
||||||
struct request
|
|
||||||
{
|
|
||||||
std::string jsonrpc;
|
|
||||||
std::string method;
|
|
||||||
epee::serialization::storage_entry id;
|
|
||||||
t_param params;
|
|
||||||
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
|
||||||
KV_SERIALIZE(jsonrpc)
|
|
||||||
KV_SERIALIZE(id)
|
|
||||||
KV_SERIALIZE(method)
|
|
||||||
KV_SERIALIZE(params)
|
|
||||||
END_KV_SERIALIZE_MAP()
|
|
||||||
};
|
|
||||||
|
|
||||||
struct error
|
|
||||||
{
|
|
||||||
int64_t code;
|
|
||||||
std::string message;
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
|
||||||
KV_SERIALIZE(code)
|
|
||||||
KV_SERIALIZE(message)
|
|
||||||
END_KV_SERIALIZE_MAP()
|
|
||||||
};
|
|
||||||
|
|
||||||
struct dummy_error
|
|
||||||
{
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
|
||||||
END_KV_SERIALIZE_MAP()
|
|
||||||
};
|
|
||||||
|
|
||||||
struct dummy_result
|
|
||||||
{
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
|
||||||
END_KV_SERIALIZE_MAP()
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename t_param, typename t_error>
|
|
||||||
struct response
|
|
||||||
{
|
|
||||||
std::string jsonrpc;
|
|
||||||
t_param result;
|
|
||||||
epee::serialization::storage_entry id;
|
|
||||||
t_error error;
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
|
||||||
KV_SERIALIZE(jsonrpc)
|
|
||||||
KV_SERIALIZE(id)
|
|
||||||
KV_SERIALIZE(result)
|
|
||||||
KV_SERIALIZE(error)
|
|
||||||
END_KV_SERIALIZE_MAP()
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename t_param>
|
|
||||||
struct response<t_param, dummy_error>
|
|
||||||
{
|
|
||||||
std::string jsonrpc;
|
|
||||||
t_param result;
|
|
||||||
epee::serialization::storage_entry id;
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
|
||||||
KV_SERIALIZE(jsonrpc)
|
|
||||||
KV_SERIALIZE(id)
|
|
||||||
KV_SERIALIZE(result)
|
|
||||||
END_KV_SERIALIZE_MAP()
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename t_error>
|
|
||||||
struct response<dummy_result, t_error>
|
|
||||||
{
|
|
||||||
std::string jsonrpc;
|
|
||||||
t_error error;
|
|
||||||
epee::serialization::storage_entry id;
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
|
||||||
KV_SERIALIZE(jsonrpc)
|
|
||||||
KV_SERIALIZE(id)
|
|
||||||
KV_SERIALIZE(error)
|
|
||||||
END_KV_SERIALIZE_MAP()
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef response<dummy_result, error> error_response;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define BEGIN_JSON_RPC_MAP(uri) else if(query_info.m_URI == uri) \
|
#define BEGIN_JSON_RPC_MAP(uri) else if(query_info.m_URI == uri) \
|
||||||
{ \
|
{ \
|
||||||
uint64_t ticks = epee::misc_utils::get_tick_count(); \
|
uint64_t ticks = epee::misc_utils::get_tick_count(); \
|
||||||
|
@ -315,6 +224,6 @@ namespace epee
|
||||||
rsp.error.message = "Method not found"; \
|
rsp.error.message = "Method not found"; \
|
||||||
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \
|
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_info.m_body); \
|
||||||
return true; \
|
return true; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,167 @@
|
||||||
|
#ifndef JSONRPC_PROTOCOL_HANDLER_H
|
||||||
|
#define JSONRPC_PROTOCOL_HANDLER_H
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include "net/net_utils_base.h"
|
||||||
|
#include "jsonrpc_structs.h"
|
||||||
|
#include "storages/portable_storage.h"
|
||||||
|
#include "storages/portable_storage_template_helper.h"
|
||||||
|
|
||||||
|
namespace epee
|
||||||
|
{
|
||||||
|
namespace net_utils
|
||||||
|
{
|
||||||
|
namespace jsonrpc2
|
||||||
|
{
|
||||||
|
inline
|
||||||
|
std::string& make_error_resp_json(int64_t code, const std::string& message,
|
||||||
|
std::string& response_data,
|
||||||
|
const epee::serialization::storage_entry& id = nullptr)
|
||||||
|
{
|
||||||
|
epee::json_rpc::error_response rsp;
|
||||||
|
rsp.id = id;
|
||||||
|
rsp.jsonrpc = "2.0";
|
||||||
|
rsp.error.code = code;
|
||||||
|
rsp.error.message = message;
|
||||||
|
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(rsp), response_data, 0, false);
|
||||||
|
response_data += "\n";
|
||||||
|
return response_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class t_connection_context>
|
||||||
|
struct i_jsonrpc2_server_handler
|
||||||
|
{
|
||||||
|
virtual ~i_jsonrpc2_server_handler()
|
||||||
|
{}
|
||||||
|
virtual bool handle_rpc_request(const std::string& req_data,
|
||||||
|
std::string& resp_data,
|
||||||
|
t_connection_context& conn_context) = 0;
|
||||||
|
virtual bool init_server_thread()
|
||||||
|
{ return true; }
|
||||||
|
virtual bool deinit_server_thread()
|
||||||
|
{ return true; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class t_connection_context>
|
||||||
|
struct jsonrpc2_server_config
|
||||||
|
{
|
||||||
|
i_jsonrpc2_server_handler<t_connection_context>* m_phandler;
|
||||||
|
critical_section m_lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<class t_connection_context = net_utils::connection_context_base>
|
||||||
|
class jsonrpc2_connection_handler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
typedef t_connection_context connection_context;
|
||||||
|
typedef jsonrpc2_server_config<t_connection_context> config_type;
|
||||||
|
|
||||||
|
jsonrpc2_connection_handler(i_service_endpoint* psnd_hndlr,
|
||||||
|
config_type& config,
|
||||||
|
t_connection_context& conn_context)
|
||||||
|
: m_psnd_hndlr(psnd_hndlr),
|
||||||
|
m_config(config),
|
||||||
|
m_conn_context(conn_context),
|
||||||
|
m_is_stop_handling(false)
|
||||||
|
{}
|
||||||
|
virtual ~jsonrpc2_connection_handler()
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool release_protocol()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
virtual bool thread_init()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
virtual bool thread_deinit()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
void handle_qued_callback()
|
||||||
|
{}
|
||||||
|
bool after_init_connection()
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
virtual bool handle_recv(const void* ptr, size_t cb)
|
||||||
|
{
|
||||||
|
std::string buf((const char*)ptr, cb);
|
||||||
|
LOG_PRINT_L0("JSONRPC2_RECV: " << ptr << "\r\n" << buf);
|
||||||
|
|
||||||
|
bool res = handle_buff_in(buf);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool handle_buff_in(std::string& buf)
|
||||||
|
{
|
||||||
|
if(m_cache.size())
|
||||||
|
m_cache += buf;
|
||||||
|
else
|
||||||
|
m_cache.swap(buf);
|
||||||
|
|
||||||
|
m_is_stop_handling = false;
|
||||||
|
while (!m_is_stop_handling) {
|
||||||
|
std::string::size_type pos = match_end_of_request(m_cache);
|
||||||
|
if (std::string::npos == pos) {
|
||||||
|
m_is_stop_handling = true;
|
||||||
|
if (m_cache.size() > 4096) {
|
||||||
|
LOG_ERROR("jsonrpc2_connection_handler::handle_buff_in: Too long request");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
extract_cached_request_and_handle(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!m_cache.size()) {
|
||||||
|
m_is_stop_handling = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
bool extract_cached_request_and_handle(std::string::size_type pos)
|
||||||
|
{
|
||||||
|
std::string request_data(m_cache.begin(), m_cache.begin() + pos);
|
||||||
|
m_cache.erase(0, pos);
|
||||||
|
return handle_request_and_send_response(request_data);
|
||||||
|
}
|
||||||
|
bool handle_request_and_send_response(const std::string& request_data)
|
||||||
|
{
|
||||||
|
CHECK_AND_ASSERT_MES(m_config.m_phandler, false, "m_config.m_phandler is NULL!!!!");
|
||||||
|
std::string response_data;
|
||||||
|
|
||||||
|
LOG_PRINT_L3("JSONRPC2_REQUEST: >> \r\n" << request_data);
|
||||||
|
bool rpc_result = m_config.m_phandler->handle_rpc_request(request_data, response_data, m_conn_context);
|
||||||
|
LOG_PRINT_L3("JSONRPC2_RESPONSE: << \r\n" << response_data);
|
||||||
|
|
||||||
|
m_psnd_hndlr->do_send((void*)response_data.data(), response_data.size());
|
||||||
|
return rpc_result;
|
||||||
|
}
|
||||||
|
std::string::size_type match_end_of_request(const std::string& buf)
|
||||||
|
{
|
||||||
|
std::string::size_type res = buf.find("\n");
|
||||||
|
if(std::string::npos != res) {
|
||||||
|
return res + 2;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
i_service_endpoint* m_psnd_hndlr;
|
||||||
|
|
||||||
|
private:
|
||||||
|
config_type& m_config;
|
||||||
|
t_connection_context& m_conn_context;
|
||||||
|
std::string m_cache;
|
||||||
|
bool m_is_stop_handling;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* JSONRPC_PROTOCOL_HANDLER_H */
|
|
@ -0,0 +1,86 @@
|
||||||
|
#ifndef JSONRPC_SERVER_HANDLERS_MAP_H
|
||||||
|
#define JSONRPC_SERVER_HANDLERS_MAP_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include "serialization/keyvalue_serialization.h"
|
||||||
|
#include "storages/portable_storage_template_helper.h"
|
||||||
|
#include "storages/portable_storage_base.h"
|
||||||
|
#include "jsonrpc_structs.h"
|
||||||
|
#include "jsonrpc_protocol_handler.h"
|
||||||
|
|
||||||
|
#define BEGIN_JSONRPC2_MAP(t_connection_context) \
|
||||||
|
bool handle_rpc_request(const std::string& req_data, \
|
||||||
|
std::string& resp_data, \
|
||||||
|
t_connection_context& m_conn_context) \
|
||||||
|
{ \
|
||||||
|
bool handled = false; \
|
||||||
|
uint64_t ticks = epee::misc_utils::get_tick_count(); \
|
||||||
|
epee::serialization::portable_storage ps; \
|
||||||
|
if (!ps.load_from_json(req_data)) \
|
||||||
|
{ \
|
||||||
|
epee::net_utils::jsonrpc2::make_error_resp_json(-32700, "Parse error", resp_data); \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
epee::serialization::storage_entry id_; \
|
||||||
|
id_ = epee::serialization::storage_entry(std::string()); \
|
||||||
|
if (!ps.get_value("id", id_, nullptr)) \
|
||||||
|
{ \
|
||||||
|
epee::net_utils::jsonrpc2::make_error_resp_json(-32600, "Invalid Request", resp_data); \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
std::string callback_name; \
|
||||||
|
if (!ps.get_value("method", callback_name, nullptr)) \
|
||||||
|
{ \
|
||||||
|
epee::net_utils::jsonrpc2::make_error_resp_json(-32600, "Invalid Request", resp_data, id_); \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
if (false) return true; //just a stub to have "else if"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#define PREPARE_JSONRPC2_OBJECTS_FROM_JSON(command_type) \
|
||||||
|
handled = true; \
|
||||||
|
boost::value_initialized<epee::json_rpc::request<command_type::request> > req_; \
|
||||||
|
epee::json_rpc::request<command_type::request>& req = static_cast<epee::json_rpc::request<command_type::request>&>(req_);\
|
||||||
|
if(!req.load(ps)) \
|
||||||
|
{ \
|
||||||
|
epee::net_utils::jsonrpc2::make_error_resp_json(-32602, "Invalid params", resp_data, req.id); \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
uint64_t ticks1 = epee::misc_utils::get_tick_count(); \
|
||||||
|
boost::value_initialized<epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error> > resp_; \
|
||||||
|
epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error>& resp = static_cast<epee::json_rpc::response<command_type::response, epee::json_rpc::dummy_error> &>(resp_); \
|
||||||
|
resp.jsonrpc = "2.0"; \
|
||||||
|
resp.id = req.id;
|
||||||
|
|
||||||
|
#define FINALIZE_JSONRPC2_OBJECTS_TO_JSON(method_name) \
|
||||||
|
uint64_t ticks2 = epee::misc_utils::get_tick_count(); \
|
||||||
|
epee::serialization::store_t_to_json(resp, resp_data, 0, false); \
|
||||||
|
resp_data += "\n"; \
|
||||||
|
uint64_t ticks3 = epee::misc_utils::get_tick_count(); \
|
||||||
|
LOG_PRINT("[" << method_name << "] processed with " << ticks1-ticks << "/"<< ticks2-ticks1 << "/" << ticks3-ticks2 << "ms", LOG_LEVEL_2);
|
||||||
|
|
||||||
|
|
||||||
|
#define MAP_JSONRPC2_WE(method_name, callback_f, command_type) \
|
||||||
|
else if (callback_name == method_name) \
|
||||||
|
{ \
|
||||||
|
PREPARE_JSONRPC2_OBJECTS_FROM_JSON(command_type) \
|
||||||
|
epee::json_rpc::error_response fail_resp = AUTO_VAL_INIT(fail_resp); \
|
||||||
|
fail_resp.jsonrpc = "2.0"; \
|
||||||
|
fail_resp.id = req.id; \
|
||||||
|
if(!callback_f(req.params, resp.result, fail_resp.error, m_conn_context)) \
|
||||||
|
{ \
|
||||||
|
epee::serialization::store_t_to_json(static_cast<epee::json_rpc::error_response&>(fail_resp), resp_data, 0, false); \
|
||||||
|
resp_data += "\n"; \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
FINALIZE_JSONRPC2_OBJECTS_TO_JSON(method_name) \
|
||||||
|
return true; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define END_JSONRPC2_MAP() \
|
||||||
|
epee::net_utils::jsonrpc2::make_error_resp_json(-32601, "Method not found", resp_data, id_); \
|
||||||
|
return true; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* JSONRPC_SERVER_HANDLERS_MAP_H */
|
|
@ -0,0 +1,84 @@
|
||||||
|
#ifndef JSONRPC_SERVER_IMPL_BASE_H
|
||||||
|
#define JSONRPC_SERVER_IMPL_BASE_H
|
||||||
|
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
|
||||||
|
#include "net/jsonrpc_protocol_handler.h"
|
||||||
|
#include "net/jsonrpc_server_handlers_map.h"
|
||||||
|
#include "net/abstract_tcp_server2.h"
|
||||||
|
|
||||||
|
namespace epee
|
||||||
|
{
|
||||||
|
|
||||||
|
template<class t_child_class, class t_connection_context = epee::net_utils::connection_context_base>
|
||||||
|
class jsonrpc_server_impl_base: public net_utils::jsonrpc2::i_jsonrpc2_server_handler<t_connection_context>
|
||||||
|
{
|
||||||
|
|
||||||
|
public:
|
||||||
|
jsonrpc_server_impl_base()
|
||||||
|
: m_net_server()
|
||||||
|
{}
|
||||||
|
|
||||||
|
explicit jsonrpc_server_impl_base(boost::asio::io_service& external_io_service)
|
||||||
|
: m_net_server(external_io_service)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool init(const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0")
|
||||||
|
{
|
||||||
|
//set self as callback handler
|
||||||
|
m_net_server.get_config_object().m_phandler = static_cast<t_child_class*>(this);
|
||||||
|
|
||||||
|
LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port);
|
||||||
|
bool res = m_net_server.init_server(bind_port, bind_ip);
|
||||||
|
if (!res)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed to bind server");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool run(size_t threads_count, bool wait = true)
|
||||||
|
{
|
||||||
|
//go to loop
|
||||||
|
LOG_PRINT("Run net_service loop( " << threads_count << " threads)...", LOG_LEVEL_0);
|
||||||
|
if(!m_net_server.run_server(threads_count, wait))
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed to run net tcp server!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wait)
|
||||||
|
LOG_PRINT("net_service loop stopped.", LOG_LEVEL_0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool deinit()
|
||||||
|
{
|
||||||
|
return m_net_server.deinit_server();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool timed_wait_server_stop(uint64_t ms)
|
||||||
|
{
|
||||||
|
return m_net_server.timed_wait_server_stop(ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool send_stop_signal()
|
||||||
|
{
|
||||||
|
m_net_server.send_stop_signal();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_binded_port()
|
||||||
|
{
|
||||||
|
return m_net_server.get_binded_port();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
net_utils::boosted_tcp_server<net_utils::jsonrpc2::jsonrpc2_connection_handler<t_connection_context> > m_net_server;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* JSONRPC_SERVER_IMPL_BASE_H */
|
||||||
|
|
|
@ -0,0 +1,96 @@
|
||||||
|
#ifndef JSONRPC_STRUCTS_H
|
||||||
|
#define JSONRPC_STRUCTS_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
#include "serialization/keyvalue_serialization.h"
|
||||||
|
#include "storages/portable_storage_base.h"
|
||||||
|
|
||||||
|
namespace epee
|
||||||
|
{
|
||||||
|
namespace json_rpc
|
||||||
|
{
|
||||||
|
template<typename t_param>
|
||||||
|
struct request
|
||||||
|
{
|
||||||
|
std::string jsonrpc;
|
||||||
|
std::string method;
|
||||||
|
epee::serialization::storage_entry id;
|
||||||
|
t_param params;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(jsonrpc)
|
||||||
|
KV_SERIALIZE(id)
|
||||||
|
KV_SERIALIZE(method)
|
||||||
|
KV_SERIALIZE(params)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct error
|
||||||
|
{
|
||||||
|
int64_t code;
|
||||||
|
std::string message;
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(code)
|
||||||
|
KV_SERIALIZE(message)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dummy_error
|
||||||
|
{
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct dummy_result
|
||||||
|
{
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename t_param, typename t_error>
|
||||||
|
struct response
|
||||||
|
{
|
||||||
|
std::string jsonrpc;
|
||||||
|
t_param result;
|
||||||
|
epee::serialization::storage_entry id;
|
||||||
|
t_error error;
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(jsonrpc)
|
||||||
|
KV_SERIALIZE(id)
|
||||||
|
KV_SERIALIZE(result)
|
||||||
|
KV_SERIALIZE(error)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename t_param>
|
||||||
|
struct response<t_param, dummy_error>
|
||||||
|
{
|
||||||
|
std::string jsonrpc;
|
||||||
|
t_param result;
|
||||||
|
epee::serialization::storage_entry id;
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(jsonrpc)
|
||||||
|
KV_SERIALIZE(id)
|
||||||
|
KV_SERIALIZE(result)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename t_error>
|
||||||
|
struct response<dummy_result, t_error>
|
||||||
|
{
|
||||||
|
std::string jsonrpc;
|
||||||
|
t_error error;
|
||||||
|
epee::serialization::storage_entry id;
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(jsonrpc)
|
||||||
|
KV_SERIALIZE(id)
|
||||||
|
KV_SERIALIZE(error)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef response<dummy_result, error> error_response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* JSONRPC_STRUCTS_H */
|
|
@ -47,8 +47,8 @@ namespace net_utils
|
||||||
struct connection_context_base
|
struct connection_context_base
|
||||||
{
|
{
|
||||||
const boost::uuids::uuid m_connection_id;
|
const boost::uuids::uuid m_connection_id;
|
||||||
const uint32_t m_remote_ip;
|
const uint32_t m_remote_ip;
|
||||||
const uint32_t m_remote_port;
|
const uint32_t m_remote_port;
|
||||||
const bool m_is_income;
|
const bool m_is_income;
|
||||||
const time_t m_started;
|
const time_t m_started;
|
||||||
time_t m_last_recv;
|
time_t m_last_recv;
|
||||||
|
@ -56,27 +56,30 @@ namespace net_utils
|
||||||
uint64_t m_recv_cnt;
|
uint64_t m_recv_cnt;
|
||||||
uint64_t m_send_cnt;
|
uint64_t m_send_cnt;
|
||||||
|
|
||||||
connection_context_base(boost::uuids::uuid connection_id, long remote_ip, int remote_port, bool is_income, time_t last_recv = 0, time_t last_send = 0, uint64_t recv_cnt = 0, uint64_t send_cnt = 0):
|
connection_context_base(boost::uuids::uuid connection_id,
|
||||||
|
long remote_ip, int remote_port, bool is_income,
|
||||||
|
time_t last_recv = 0, time_t last_send = 0,
|
||||||
|
uint64_t recv_cnt = 0, uint64_t send_cnt = 0):
|
||||||
m_connection_id(connection_id),
|
m_connection_id(connection_id),
|
||||||
m_remote_ip(remote_ip),
|
m_remote_ip(remote_ip),
|
||||||
m_remote_port(remote_port),
|
m_remote_port(remote_port),
|
||||||
m_is_income(is_income),
|
m_is_income(is_income),
|
||||||
|
m_started(time(NULL)),
|
||||||
m_last_recv(last_recv),
|
m_last_recv(last_recv),
|
||||||
m_last_send(last_send),
|
m_last_send(last_send),
|
||||||
m_recv_cnt(recv_cnt),
|
m_recv_cnt(recv_cnt),
|
||||||
m_send_cnt(send_cnt),
|
m_send_cnt(send_cnt)
|
||||||
m_started(time(NULL))
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
connection_context_base(): m_connection_id(),
|
connection_context_base(): m_connection_id(),
|
||||||
m_remote_ip(0),
|
m_remote_ip(0),
|
||||||
m_remote_port(0),
|
m_remote_port(0),
|
||||||
m_is_income(false),
|
m_is_income(false),
|
||||||
|
m_started(time(NULL)),
|
||||||
m_last_recv(0),
|
m_last_recv(0),
|
||||||
m_last_send(0),
|
m_last_send(0),
|
||||||
m_recv_cnt(0),
|
m_recv_cnt(0),
|
||||||
m_send_cnt(0),
|
m_send_cnt(0)
|
||||||
m_started(time(NULL))
|
|
||||||
{}
|
{}
|
||||||
|
|
||||||
connection_context_base& operator=(const connection_context_base& a)
|
connection_context_base& operator=(const connection_context_base& a)
|
||||||
|
|
|
@ -51,13 +51,13 @@ namespace epee
|
||||||
#define PROFILE_FUNC_THIRD(immortal_ptr_str)
|
#define PROFILE_FUNC_THIRD(immortal_ptr_str)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define START_WAY_POINTS() uint64_t _____way_point_time = misc_utils::get_tick_count();
|
#define START_WAY_POINTS() uint64_t _____way_point_time = epee::misc_utils::get_tick_count();
|
||||||
#define WAY_POINT(name) {uint64_t delta = misc_utils::get_tick_count()-_____way_point_time; LOG_PRINT("Way point " << name << ": " << delta, LOG_LEVEL_2);_____way_point_time = misc_utils::get_tick_count();}
|
#define WAY_POINT(name) {uint64_t delta = epee::misc_utils::get_tick_count()-_____way_point_time; LOG_PRINT("Way point " << name << ": " << delta, LOG_LEVEL_2);_____way_point_time = misc_utils::get_tick_count();}
|
||||||
#define WAY_POINT2(name, avrg_obj) {uint64_t delta = misc_utils::get_tick_count()-_____way_point_time; avrg_obj.push(delta); LOG_PRINT("Way point " << name << ": " << delta, LOG_LEVEL_2);_____way_point_time = misc_utils::get_tick_count();}
|
#define WAY_POINT2(name, avrg_obj) {uint64_t delta = epee::misc_utils::get_tick_count()-_____way_point_time; avrg_obj.push(delta); LOG_PRINT("Way point " << name << ": " << delta, LOG_LEVEL_2);_____way_point_time = misc_utils::get_tick_count();}
|
||||||
|
|
||||||
|
|
||||||
#define TIME_MEASURE_START(var_name) uint64_t var_name = misc_utils::get_tick_count();
|
#define TIME_MEASURE_START(var_name) uint64_t var_name = epee::misc_utils::get_tick_count();
|
||||||
#define TIME_MEASURE_FINISH(var_name) var_name = misc_utils::get_tick_count() - var_name;
|
#define TIME_MEASURE_FINISH(var_name) var_name = epee::misc_utils::get_tick_count() - var_name;
|
||||||
|
|
||||||
namespace profile_tools
|
namespace profile_tools
|
||||||
{
|
{
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
#include "misc_log_ex.h"
|
#include "misc_log_ex.h"
|
||||||
#include "enableable.h"
|
#include "enableable.h"
|
||||||
#include "keyvalue_serialization_overloads.h"
|
#include "keyvalue_serialization_overloads.h"
|
||||||
|
#include "serialization/serialization.h"
|
||||||
|
|
||||||
namespace epee
|
namespace epee
|
||||||
{
|
{
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
@ -41,12 +43,12 @@ public: \
|
||||||
template<class t_storage> \
|
template<class t_storage> \
|
||||||
bool store( t_storage& st, typename t_storage::hsection hparent_section = nullptr) const\
|
bool store( t_storage& st, typename t_storage::hsection hparent_section = nullptr) const\
|
||||||
{\
|
{\
|
||||||
return serialize_map<true>(*this, st, hparent_section);\
|
return serialize_map<true>(*this, st, hparent_section);\
|
||||||
}\
|
}\
|
||||||
template<class t_storage> \
|
template<class t_storage> \
|
||||||
bool _load( t_storage& stg, typename t_storage::hsection hparent_section = nullptr)\
|
bool _load( t_storage& stg, typename t_storage::hsection hparent_section = nullptr)\
|
||||||
{\
|
{\
|
||||||
return serialize_map<false>(*this, stg, hparent_section);\
|
return serialize_map<false>(*this, stg, hparent_section);\
|
||||||
}\
|
}\
|
||||||
template<class t_storage> \
|
template<class t_storage> \
|
||||||
bool load( t_storage& stg, typename t_storage::hsection hparent_section = nullptr)\
|
bool load( t_storage& stg, typename t_storage::hsection hparent_section = nullptr)\
|
||||||
|
|
|
@ -83,7 +83,7 @@ namespace epee
|
||||||
bool load_from_binary(const binarybuffer& target);
|
bool load_from_binary(const binarybuffer& target);
|
||||||
template<class trace_policy>
|
template<class trace_policy>
|
||||||
bool dump_as_xml(std::string& targetObj, const std::string& root_name = "");
|
bool dump_as_xml(std::string& targetObj, const std::string& root_name = "");
|
||||||
bool dump_as_json(std::string& targetObj, size_t indent = 0);
|
bool dump_as_json(std::string& targetObj, size_t indent = 0, bool insert_newlines = true);
|
||||||
bool load_from_json(const std::string& source);
|
bool load_from_json(const std::string& source);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -106,17 +106,17 @@ namespace epee
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
};
|
};
|
||||||
inline
|
inline
|
||||||
bool portable_storage::dump_as_json(std::string& buff, size_t indent)
|
bool portable_storage::dump_as_json(std::string& buff, size_t indent, bool insert_newlines)
|
||||||
{
|
{
|
||||||
TRY_ENTRY();
|
TRY_ENTRY();
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
epee::serialization::dump_as_json(ss, m_root, indent);
|
epee::serialization::dump_as_json(ss, m_root, indent, insert_newlines);
|
||||||
buff = ss.str();
|
buff = ss.str();
|
||||||
return true;
|
return true;
|
||||||
CATCH_ENTRY("portable_storage::dump_as_json", false)
|
CATCH_ENTRY("portable_storage::dump_as_json", false)
|
||||||
}
|
}
|
||||||
inline
|
inline
|
||||||
bool portable_storage::load_from_json(const std::string& source)
|
bool portable_storage::load_from_json(const std::string& source)
|
||||||
{
|
{
|
||||||
TRY_ENTRY();
|
TRY_ENTRY();
|
||||||
return json::load_from_json(source, *this);
|
return json::load_from_json(source, *this);
|
||||||
|
@ -124,13 +124,13 @@ namespace epee
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class trace_policy>
|
template<class trace_policy>
|
||||||
bool portable_storage::dump_as_xml(std::string& targetObj, const std::string& root_name)
|
bool portable_storage::dump_as_xml(std::string& targetObj, const std::string& root_name)
|
||||||
{
|
{
|
||||||
return false;//TODO: don't think i ever again will use xml - ambiguous and "overtagged" format
|
return false;//TODO: don't think i ever again will use xml - ambiguous and "overtagged" format
|
||||||
}
|
}
|
||||||
|
|
||||||
inline
|
inline
|
||||||
bool portable_storage::store_to_binary(binarybuffer& target)
|
bool portable_storage::store_to_binary(binarybuffer& target)
|
||||||
{
|
{
|
||||||
TRY_ENTRY();
|
TRY_ENTRY();
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
@ -145,7 +145,7 @@ namespace epee
|
||||||
CATCH_ENTRY("portable_storage::store_to_binary", false)
|
CATCH_ENTRY("portable_storage::store_to_binary", false)
|
||||||
}
|
}
|
||||||
inline
|
inline
|
||||||
bool portable_storage::load_from_binary(const binarybuffer& source)
|
bool portable_storage::load_from_binary(const binarybuffer& source)
|
||||||
{
|
{
|
||||||
m_root.m_entries.clear();
|
m_root.m_entries.clear();
|
||||||
if(source.size() < sizeof(storage_block_header))
|
if(source.size() < sizeof(storage_block_header))
|
||||||
|
@ -174,7 +174,7 @@ namespace epee
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------
|
||||||
inline
|
inline
|
||||||
hsection portable_storage::open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist)
|
hsection portable_storage::open_section(const std::string& section_name, hsection hparent_section, bool create_if_notexist)
|
||||||
{
|
{
|
||||||
TRY_ENTRY();
|
TRY_ENTRY();
|
||||||
hparent_section = hparent_section ? hparent_section:&m_root;
|
hparent_section = hparent_section ? hparent_section:&m_root;
|
||||||
|
@ -238,7 +238,7 @@ namespace epee
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------
|
||||||
template<class t_value>
|
template<class t_value>
|
||||||
bool portable_storage::set_value(const std::string& value_name, const t_value& v, hsection hparent_section)
|
bool portable_storage::set_value(const std::string& value_name, const t_value& v, hsection hparent_section)
|
||||||
{
|
{
|
||||||
BOOST_MPL_ASSERT(( boost::mpl::contains<boost::mpl::push_front<storage_entry::types, storage_entry>::type, t_value> ));
|
BOOST_MPL_ASSERT(( boost::mpl::contains<boost::mpl::push_front<storage_entry::types, storage_entry>::type, t_value> ));
|
||||||
TRY_ENTRY();
|
TRY_ENTRY();
|
||||||
|
@ -345,7 +345,7 @@ namespace epee
|
||||||
|
|
||||||
|
|
||||||
template<class t_value>
|
template<class t_value>
|
||||||
bool portable_storage::get_next_value(harray hval_array, t_value& target)
|
bool portable_storage::get_next_value(harray hval_array, t_value& target)
|
||||||
{
|
{
|
||||||
BOOST_MPL_ASSERT(( boost::mpl::contains<storage_entry::types, t_value> ));
|
BOOST_MPL_ASSERT(( boost::mpl::contains<storage_entry::types, t_value> ));
|
||||||
//TRY_ENTRY();
|
//TRY_ENTRY();
|
||||||
|
@ -462,7 +462,7 @@ namespace epee
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------------------------------------
|
||||||
inline
|
inline
|
||||||
bool portable_storage::insert_next_section(harray hsec_array, hsection& hinserted_childsection)
|
bool portable_storage::insert_next_section(harray hsec_array, hsection& hinserted_childsection)
|
||||||
{
|
{
|
||||||
TRY_ENTRY();
|
TRY_ENTRY();
|
||||||
CHECK_AND_ASSERT(hsec_array, false);
|
CHECK_AND_ASSERT(hsec_array, false);
|
||||||
|
|
|
@ -25,6 +25,9 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#include "parserse_base_utils.h"
|
#include "parserse_base_utils.h"
|
||||||
#include "portable_storage.h"
|
#include "portable_storage.h"
|
||||||
#include "file_io_utils.h"
|
#include "file_io_utils.h"
|
||||||
|
@ -56,19 +59,19 @@ namespace epee
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------------
|
||||||
template<class t_struct>
|
template<class t_struct>
|
||||||
bool store_t_to_json(t_struct& str_in, std::string& json_buff, size_t indent = 0)
|
bool store_t_to_json(t_struct& str_in, std::string& json_buff, size_t indent = 0, bool insert_newlines = true)
|
||||||
{
|
{
|
||||||
portable_storage ps;
|
portable_storage ps;
|
||||||
str_in.store(ps);
|
str_in.store(ps);
|
||||||
ps.dump_as_json(json_buff, indent);
|
ps.dump_as_json(json_buff, indent, insert_newlines);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------------
|
||||||
template<class t_struct>
|
template<class t_struct>
|
||||||
std::string store_t_to_json(t_struct& str_in, size_t indent = 0)
|
std::string store_t_to_json(t_struct& str_in, size_t indent = 0, bool insert_newlines = true)
|
||||||
{
|
{
|
||||||
std::string json_buff;
|
std::string json_buff;
|
||||||
store_t_to_json(str_in, json_buff, indent);
|
store_t_to_json(str_in, json_buff, indent, insert_newlines);
|
||||||
return std::move(json_buff);
|
return std::move(json_buff);
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------------
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
#include "misc_language.h"
|
#include "misc_language.h"
|
||||||
#include "portable_storage_base.h"
|
#include "portable_storage_base.h"
|
||||||
|
#include "parserse_base_utils.h"
|
||||||
|
|
||||||
namespace epee
|
namespace epee
|
||||||
{
|
{
|
||||||
|
@ -37,21 +38,21 @@ namespace epee
|
||||||
{
|
{
|
||||||
|
|
||||||
template<class t_stream>
|
template<class t_stream>
|
||||||
void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent);
|
void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent, bool insert_newlines);
|
||||||
template<class t_stream>
|
template<class t_stream>
|
||||||
void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent);
|
void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent, bool insert_newlines);
|
||||||
template<class t_stream>
|
template<class t_stream>
|
||||||
void dump_as_json(t_stream& strm, const std::string& v, size_t indent);
|
void dump_as_json(t_stream& strm, const std::string& v, size_t indent, bool insert_newlines);
|
||||||
template<class t_stream>
|
template<class t_stream>
|
||||||
void dump_as_json(t_stream& strm, const int8_t& v, size_t indent);
|
void dump_as_json(t_stream& strm, const int8_t& v, size_t indent, bool insert_newlines);
|
||||||
template<class t_stream>
|
template<class t_stream>
|
||||||
void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent);
|
void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent, bool insert_newlines);
|
||||||
template<class t_stream>
|
template<class t_stream>
|
||||||
void dump_as_json(t_stream& strm, const bool& v, size_t indent);
|
void dump_as_json(t_stream& strm, const bool& v, size_t indent, bool insert_newlines);
|
||||||
template<class t_stream, class t_type>
|
template<class t_stream, class t_type>
|
||||||
void dump_as_json(t_stream& strm, const t_type& v, size_t indent);
|
void dump_as_json(t_stream& strm, const t_type& v, size_t indent, bool insert_newlines);
|
||||||
template<class t_stream>
|
template<class t_stream>
|
||||||
void dump_as_json(t_stream& strm, const section& sec, size_t indent);
|
void dump_as_json(t_stream& strm, const section& sec, size_t indent, bool insert_newlines);
|
||||||
|
|
||||||
|
|
||||||
inline std::string make_indent(size_t indent)
|
inline std::string make_indent(size_t indent)
|
||||||
|
@ -64,7 +65,11 @@ namespace epee
|
||||||
{
|
{
|
||||||
t_stream& m_strm;
|
t_stream& m_strm;
|
||||||
size_t m_indent;
|
size_t m_indent;
|
||||||
array_entry_store_to_json_visitor(t_stream& strm, size_t indent):m_strm(strm), m_indent(indent){}
|
bool m_insert_newlines;
|
||||||
|
array_entry_store_to_json_visitor(t_stream& strm, size_t indent,
|
||||||
|
bool insert_newlines = true)
|
||||||
|
: m_strm(strm), m_indent(indent), m_insert_newlines(insert_newlines)
|
||||||
|
{}
|
||||||
|
|
||||||
template<class t_type>
|
template<class t_type>
|
||||||
void operator()(const array_entry_t<t_type>& a)
|
void operator()(const array_entry_t<t_type>& a)
|
||||||
|
@ -75,7 +80,7 @@ namespace epee
|
||||||
auto last_it = --a.m_array.end();
|
auto last_it = --a.m_array.end();
|
||||||
for(auto it = a.m_array.begin(); it != a.m_array.end(); it++)
|
for(auto it = a.m_array.begin(); it != a.m_array.end(); it++)
|
||||||
{
|
{
|
||||||
dump_as_json(m_strm, *it, m_indent);
|
dump_as_json(m_strm, *it, m_indent, m_insert_newlines);
|
||||||
if(it != last_it)
|
if(it != last_it)
|
||||||
m_strm << ",";
|
m_strm << ",";
|
||||||
}
|
}
|
||||||
|
@ -89,50 +94,53 @@ namespace epee
|
||||||
{
|
{
|
||||||
t_stream& m_strm;
|
t_stream& m_strm;
|
||||||
size_t m_indent;
|
size_t m_indent;
|
||||||
storage_entry_store_to_json_visitor(t_stream& strm, size_t indent):m_strm(strm), m_indent(indent)
|
bool m_insert_newlines;
|
||||||
|
storage_entry_store_to_json_visitor(t_stream& strm, size_t indent,
|
||||||
|
bool insert_newlines = true)
|
||||||
|
: m_strm(strm), m_indent(indent), m_insert_newlines(insert_newlines)
|
||||||
{}
|
{}
|
||||||
//section, array_entry
|
//section, array_entry
|
||||||
template<class visited_type>
|
template<class visited_type>
|
||||||
void operator()(const visited_type& v)
|
void operator()(const visited_type& v)
|
||||||
{
|
{
|
||||||
dump_as_json(m_strm, v, m_indent);
|
dump_as_json(m_strm, v, m_indent, m_insert_newlines);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class t_stream>
|
template<class t_stream>
|
||||||
void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent)
|
void dump_as_json(t_stream& strm, const array_entry& ae, size_t indent, bool insert_newlines)
|
||||||
{
|
{
|
||||||
array_entry_store_to_json_visitor<t_stream> aesv(strm, indent);
|
array_entry_store_to_json_visitor<t_stream> aesv(strm, indent, insert_newlines);
|
||||||
boost::apply_visitor(aesv, ae);
|
boost::apply_visitor(aesv, ae);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class t_stream>
|
template<class t_stream>
|
||||||
void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent)
|
void dump_as_json(t_stream& strm, const storage_entry& se, size_t indent, bool insert_newlines)
|
||||||
{
|
{
|
||||||
storage_entry_store_to_json_visitor<t_stream> sv(strm, indent);
|
storage_entry_store_to_json_visitor<t_stream> sv(strm, indent, insert_newlines);
|
||||||
boost::apply_visitor(sv, se);
|
boost::apply_visitor(sv, se);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class t_stream>
|
template<class t_stream>
|
||||||
void dump_as_json(t_stream& strm, const std::string& v, size_t indent)
|
void dump_as_json(t_stream& strm, const std::string& v, size_t indent, bool insert_newlines)
|
||||||
{
|
{
|
||||||
strm << "\"" << misc_utils::parse::transform_to_escape_sequence(v) << "\"";
|
strm << "\"" << misc_utils::parse::transform_to_escape_sequence(v) << "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class t_stream>
|
template<class t_stream>
|
||||||
void dump_as_json(t_stream& strm, const int8_t& v, size_t indent)
|
void dump_as_json(t_stream& strm, const int8_t& v, size_t indent, bool insert_newlines)
|
||||||
{
|
{
|
||||||
strm << static_cast<int32_t>(v);
|
strm << static_cast<int32_t>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class t_stream>
|
template<class t_stream>
|
||||||
void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent)
|
void dump_as_json(t_stream& strm, const uint8_t& v, size_t indent, bool insert_newlines)
|
||||||
{
|
{
|
||||||
strm << static_cast<int32_t>(v);
|
strm << static_cast<int32_t>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class t_stream>
|
template<class t_stream>
|
||||||
void dump_as_json(t_stream& strm, const bool& v, size_t indent)
|
void dump_as_json(t_stream& strm, const bool& v, size_t indent, bool insert_newlines)
|
||||||
{
|
{
|
||||||
if(v)
|
if(v)
|
||||||
strm << "true";
|
strm << "true";
|
||||||
|
@ -143,16 +151,17 @@ namespace epee
|
||||||
|
|
||||||
|
|
||||||
template<class t_stream, class t_type>
|
template<class t_stream, class t_type>
|
||||||
void dump_as_json(t_stream& strm, const t_type& v, size_t indent)
|
void dump_as_json(t_stream& strm, const t_type& v, size_t indent, bool insert_newlines)
|
||||||
{
|
{
|
||||||
strm << v;
|
strm << v;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class t_stream>
|
template<class t_stream>
|
||||||
void dump_as_json(t_stream& strm, const section& sec, size_t indent)
|
void dump_as_json(t_stream& strm, const section& sec, size_t indent, bool insert_newlines)
|
||||||
{
|
{
|
||||||
size_t local_indent = indent + 1;
|
size_t local_indent = indent + 1;
|
||||||
strm << "{\r\n";
|
std::string newline = insert_newlines ? "\r\n" : "";
|
||||||
|
strm << "{" << newline;
|
||||||
std::string indent_str = make_indent(local_indent);
|
std::string indent_str = make_indent(local_indent);
|
||||||
if(sec.m_entries.size())
|
if(sec.m_entries.size())
|
||||||
{
|
{
|
||||||
|
@ -160,10 +169,10 @@ namespace epee
|
||||||
for(auto it = sec.m_entries.begin(); it!= sec.m_entries.end();it++)
|
for(auto it = sec.m_entries.begin(); it!= sec.m_entries.end();it++)
|
||||||
{
|
{
|
||||||
strm << indent_str << "\"" << misc_utils::parse::transform_to_escape_sequence(it->first) << "\"" << ": ";
|
strm << indent_str << "\"" << misc_utils::parse::transform_to_escape_sequence(it->first) << "\"" << ": ";
|
||||||
dump_as_json(strm, it->second, local_indent);
|
dump_as_json(strm, it->second, local_indent, insert_newlines);
|
||||||
if(it_last != it)
|
if(it_last != it)
|
||||||
strm << ",";
|
strm << ",";
|
||||||
strm << "\r\n";
|
strm << newline;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strm << make_indent(indent) << "}";
|
strm << make_indent(indent) << "}";
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
//#include <objbase.h>
|
//#include <objbase.h>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <iomanip>
|
||||||
//#include <strsafe.h>
|
//#include <strsafe.h>
|
||||||
#include <boost/uuid/uuid.hpp>
|
#include <boost/uuid/uuid.hpp>
|
||||||
#include <boost/uuid/uuid_io.hpp>
|
#include <boost/uuid/uuid_io.hpp>
|
||||||
|
|
|
@ -30,13 +30,13 @@ add_library(cryptonote_core ${CRYPTONOTE_CORE})
|
||||||
add_executable(daemon ${DAEMON} ${P2P} ${CRYPTONOTE_PROTOCOL})
|
add_executable(daemon ${DAEMON} ${P2P} ${CRYPTONOTE_PROTOCOL})
|
||||||
add_executable(connectivity_tool ${CONN_TOOL})
|
add_executable(connectivity_tool ${CONN_TOOL})
|
||||||
add_executable(simpleminer ${MINER})
|
add_executable(simpleminer ${MINER})
|
||||||
target_link_libraries(daemon rpc cryptonote_core crypto common upnpc-static ${Boost_LIBRARIES})
|
target_link_libraries(daemon rpc cryptonote_core crypto common upnpc-static ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||||
target_link_libraries(connectivity_tool cryptonote_core crypto common ${Boost_LIBRARIES})
|
target_link_libraries(connectivity_tool cryptonote_core crypto common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||||
target_link_libraries(simpleminer cryptonote_core crypto common ${Boost_LIBRARIES})
|
target_link_libraries(simpleminer cryptonote_core crypto common ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||||
add_library(rpc ${RPC})
|
add_library(rpc ${RPC})
|
||||||
add_library(wallet ${WALLET})
|
add_library(wallet ${WALLET})
|
||||||
add_executable(simplewallet ${SIMPLEWALLET} )
|
add_executable(simplewallet ${SIMPLEWALLET} )
|
||||||
target_link_libraries(simplewallet wallet rpc cryptonote_core crypto common upnpc-static ${Boost_LIBRARIES})
|
target_link_libraries(simplewallet wallet rpc cryptonote_core crypto common upnpc-static ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||||
add_dependencies(daemon version)
|
add_dependencies(daemon version)
|
||||||
add_dependencies(rpc version)
|
add_dependencies(rpc version)
|
||||||
add_dependencies(simplewallet version)
|
add_dependencies(simplewallet version)
|
||||||
|
|
|
@ -3,9 +3,21 @@
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include "command_line.h"
|
#include "command_line.h"
|
||||||
|
#include "string_tools.h"
|
||||||
|
|
||||||
namespace command_line
|
namespace command_line
|
||||||
{
|
{
|
||||||
|
std::string input_line(const std::string& prompt)
|
||||||
|
{
|
||||||
|
std::cout << prompt;
|
||||||
|
|
||||||
|
std::string buf;
|
||||||
|
std::getline(std::cin, buf);
|
||||||
|
|
||||||
|
return epee::string_tools::trim(buf);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
const arg_descriptor<bool> arg_help = {"help", "Produce help message"};
|
const arg_descriptor<bool> arg_help = {"help", "Produce help message"};
|
||||||
const arg_descriptor<bool> arg_version = {"version", "Output version information"};
|
const arg_descriptor<bool> arg_version = {"version", "Output version information"};
|
||||||
const arg_descriptor<std::string> arg_data_dir = {"data-dir", "Specify data directory"};
|
const arg_descriptor<std::string> arg_data_dir = {"data-dir", "Specify data directory"};
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
|
|
||||||
namespace command_line
|
namespace command_line
|
||||||
{
|
{
|
||||||
|
|
||||||
|
std::string input_line(const std::string& prompt);
|
||||||
|
|
||||||
template<typename T, bool required = false>
|
template<typename T, bool required = false>
|
||||||
struct arg_descriptor;
|
struct arg_descriptor;
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,14 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
// FIXME: Why is this ifdef needed? Hopefully making it struct won't break things.
|
||||||
|
|
||||||
|
/*
|
||||||
#if defined(_MSC_VER)
|
#if defined(_MSC_VER)
|
||||||
#define POD_CLASS struct
|
#define POD_CLASS struct
|
||||||
#else
|
#else
|
||||||
#define POD_CLASS class
|
#define POD_CLASS class
|
||||||
#endif
|
#endif
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define POD_CLASS struct
|
||||||
|
|
|
@ -0,0 +1,177 @@
|
||||||
|
/*
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Copyright (c) 1998-2013, Brian Gladman, Worcester, UK. All rights reserved.
|
||||||
|
|
||||||
|
The redistribution and use of this software (with or without changes)
|
||||||
|
is allowed without the payment of fees or royalties provided that:
|
||||||
|
|
||||||
|
source code distributions include the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer;
|
||||||
|
|
||||||
|
binary distributions include the above copyright notice, this list
|
||||||
|
of conditions and the following disclaimer in their documentation.
|
||||||
|
|
||||||
|
This software is provided 'as is' with no explicit or implied warranties
|
||||||
|
in respect of its operation, including, but not limited to, correctness
|
||||||
|
and fitness for purpose.
|
||||||
|
---------------------------------------------------------------------------
|
||||||
|
Issue Date: 20/12/2007
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TABLE_ALIGN 32
|
||||||
|
#define WPOLY 0x011b
|
||||||
|
#define N_COLS 4
|
||||||
|
#define AES_BLOCK_SIZE 16
|
||||||
|
#define RC_LENGTH (5 * (AES_BLOCK_SIZE / 4 - 2))
|
||||||
|
|
||||||
|
#if defined(_MSC_VER)
|
||||||
|
#define ALIGN __declspec(align(TABLE_ALIGN))
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define ALIGN __attribute__ ((aligned(16)))
|
||||||
|
#else
|
||||||
|
#define ALIGN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define rf1(r,c) (r)
|
||||||
|
#define word_in(x,c) (*((uint32_t*)(x)+(c)))
|
||||||
|
#define word_out(x,c,v) (*((uint32_t*)(x)+(c)) = (v))
|
||||||
|
|
||||||
|
#define s(x,c) x[c]
|
||||||
|
#define si(y,x,c) (s(y,c) = word_in(x, c))
|
||||||
|
#define so(y,x,c) word_out(y, c, s(x,c))
|
||||||
|
#define state_in(y,x) si(y,x,0); si(y,x,1); si(y,x,2); si(y,x,3)
|
||||||
|
#define state_out(y,x) so(y,x,0); so(y,x,1); so(y,x,2); so(y,x,3)
|
||||||
|
#define round(rm,y,x,k) rm(y,x,k,0); rm(y,x,k,1); rm(y,x,k,2); rm(y,x,k,3)
|
||||||
|
#define to_byte(x) ((x) & 0xff)
|
||||||
|
#define bval(x,n) to_byte((x) >> (8 * (n)))
|
||||||
|
|
||||||
|
#define fwd_var(x,r,c)\
|
||||||
|
( r == 0 ? ( c == 0 ? s(x,0) : c == 1 ? s(x,1) : c == 2 ? s(x,2) : s(x,3))\
|
||||||
|
: r == 1 ? ( c == 0 ? s(x,1) : c == 1 ? s(x,2) : c == 2 ? s(x,3) : s(x,0))\
|
||||||
|
: r == 2 ? ( c == 0 ? s(x,2) : c == 1 ? s(x,3) : c == 2 ? s(x,0) : s(x,1))\
|
||||||
|
: ( c == 0 ? s(x,3) : c == 1 ? s(x,0) : c == 2 ? s(x,1) : s(x,2)))
|
||||||
|
|
||||||
|
#define fwd_rnd(y,x,k,c) (s(y,c) = (k)[c] ^ four_tables(x,t_use(f,n),fwd_var,rf1,c))
|
||||||
|
|
||||||
|
#define sb_data(w) {\
|
||||||
|
w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\
|
||||||
|
w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\
|
||||||
|
w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\
|
||||||
|
w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\
|
||||||
|
w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\
|
||||||
|
w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\
|
||||||
|
w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\
|
||||||
|
w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\
|
||||||
|
w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\
|
||||||
|
w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\
|
||||||
|
w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\
|
||||||
|
w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\
|
||||||
|
w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\
|
||||||
|
w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\
|
||||||
|
w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\
|
||||||
|
w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\
|
||||||
|
w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\
|
||||||
|
w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\
|
||||||
|
w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\
|
||||||
|
w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\
|
||||||
|
w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\
|
||||||
|
w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\
|
||||||
|
w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\
|
||||||
|
w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\
|
||||||
|
w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\
|
||||||
|
w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\
|
||||||
|
w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\
|
||||||
|
w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\
|
||||||
|
w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\
|
||||||
|
w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\
|
||||||
|
w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\
|
||||||
|
w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) }
|
||||||
|
|
||||||
|
#define rc_data(w) {\
|
||||||
|
w(0x01), w(0x02), w(0x04), w(0x08), w(0x10),w(0x20), w(0x40), w(0x80),\
|
||||||
|
w(0x1b), w(0x36) }
|
||||||
|
|
||||||
|
#define bytes2word(b0, b1, b2, b3) (((uint32_t)(b3) << 24) | \
|
||||||
|
((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0))
|
||||||
|
|
||||||
|
#define h0(x) (x)
|
||||||
|
#define w0(p) bytes2word(p, 0, 0, 0)
|
||||||
|
#define w1(p) bytes2word(0, p, 0, 0)
|
||||||
|
#define w2(p) bytes2word(0, 0, p, 0)
|
||||||
|
#define w3(p) bytes2word(0, 0, 0, p)
|
||||||
|
|
||||||
|
#define u0(p) bytes2word(f2(p), p, p, f3(p))
|
||||||
|
#define u1(p) bytes2word(f3(p), f2(p), p, p)
|
||||||
|
#define u2(p) bytes2word(p, f3(p), f2(p), p)
|
||||||
|
#define u3(p) bytes2word(p, p, f3(p), f2(p))
|
||||||
|
|
||||||
|
#define v0(p) bytes2word(fe(p), f9(p), fd(p), fb(p))
|
||||||
|
#define v1(p) bytes2word(fb(p), fe(p), f9(p), fd(p))
|
||||||
|
#define v2(p) bytes2word(fd(p), fb(p), fe(p), f9(p))
|
||||||
|
#define v3(p) bytes2word(f9(p), fd(p), fb(p), fe(p))
|
||||||
|
|
||||||
|
#define f2(x) ((x<<1) ^ (((x>>7) & 1) * WPOLY))
|
||||||
|
#define f4(x) ((x<<2) ^ (((x>>6) & 1) * WPOLY) ^ (((x>>6) & 2) * WPOLY))
|
||||||
|
#define f8(x) ((x<<3) ^ (((x>>5) & 1) * WPOLY) ^ (((x>>5) & 2) * WPOLY) ^ (((x>>5) & 4) * WPOLY))
|
||||||
|
#define f3(x) (f2(x) ^ x)
|
||||||
|
#define f9(x) (f8(x) ^ x)
|
||||||
|
#define fb(x) (f8(x) ^ f2(x) ^ x)
|
||||||
|
#define fd(x) (f8(x) ^ f4(x) ^ x)
|
||||||
|
#define fe(x) (f8(x) ^ f4(x) ^ f2(x))
|
||||||
|
|
||||||
|
#define t_dec(m,n) t_##m##n
|
||||||
|
#define t_set(m,n) t_##m##n
|
||||||
|
#define t_use(m,n) t_##m##n
|
||||||
|
|
||||||
|
#define d_4(t,n,b,e,f,g,h) ALIGN const t n[4][256] = { b(e), b(f), b(g), b(h) }
|
||||||
|
|
||||||
|
#define four_tables(x,tab,vf,rf,c) \
|
||||||
|
(tab[0][bval(vf(x,0,c),rf(0,c))] \
|
||||||
|
^ tab[1][bval(vf(x,1,c),rf(1,c))] \
|
||||||
|
^ tab[2][bval(vf(x,2,c),rf(2,c))] \
|
||||||
|
^ tab[3][bval(vf(x,3,c),rf(3,c))])
|
||||||
|
|
||||||
|
d_4(uint32_t, t_dec(f,n), sb_data, u0, u1, u2, u3);
|
||||||
|
|
||||||
|
void aesb_single_round(const uint8_t *in, uint8_t *out, uint8_t *expandedKey)
|
||||||
|
{
|
||||||
|
uint32_t b0[4], b1[4];
|
||||||
|
const uint32_t *kp = (uint32_t *) expandedKey;
|
||||||
|
state_in(b0, in);
|
||||||
|
|
||||||
|
round(fwd_rnd, b1, b0, kp);
|
||||||
|
|
||||||
|
state_out(out, b1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void aesb_pseudo_round(const uint8_t *in, uint8_t *out, uint8_t *expandedKey)
|
||||||
|
{
|
||||||
|
uint32_t b0[4], b1[4];
|
||||||
|
const uint32_t *kp = (uint32_t *) expandedKey;
|
||||||
|
state_in(b0, in);
|
||||||
|
|
||||||
|
round(fwd_rnd, b1, b0, kp);
|
||||||
|
round(fwd_rnd, b0, b1, kp + 1 * N_COLS);
|
||||||
|
round(fwd_rnd, b1, b0, kp + 2 * N_COLS);
|
||||||
|
round(fwd_rnd, b0, b1, kp + 3 * N_COLS);
|
||||||
|
round(fwd_rnd, b1, b0, kp + 4 * N_COLS);
|
||||||
|
round(fwd_rnd, b0, b1, kp + 5 * N_COLS);
|
||||||
|
round(fwd_rnd, b1, b0, kp + 6 * N_COLS);
|
||||||
|
round(fwd_rnd, b0, b1, kp + 7 * N_COLS);
|
||||||
|
round(fwd_rnd, b1, b0, kp + 8 * N_COLS);
|
||||||
|
round(fwd_rnd, b0, b1, kp + 9 * N_COLS);
|
||||||
|
|
||||||
|
state_out(out, b0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__cplusplus)
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -50,6 +50,7 @@ namespace crypto {
|
||||||
return &reinterpret_cast<const unsigned char &>(scalar);
|
return &reinterpret_cast<const unsigned char &>(scalar);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* generate a random 32-byte (256-bit) integer and copy it to res */
|
||||||
static inline void random_scalar(ec_scalar &res) {
|
static inline void random_scalar(ec_scalar &res) {
|
||||||
unsigned char tmp[64];
|
unsigned char tmp[64];
|
||||||
generate_random_bytes(64, tmp);
|
generate_random_bytes(64, tmp);
|
||||||
|
@ -62,12 +63,32 @@ namespace crypto {
|
||||||
sc_reduce32(&res);
|
sc_reduce32(&res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void crypto_ops::generate_keys(public_key &pub, secret_key &sec) {
|
/*
|
||||||
|
* generate public and secret keys from a random 256-bit integer
|
||||||
|
* TODO: allow specifiying random value (for wallet recovery)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
secret_key crypto_ops::generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover) {
|
||||||
lock_guard<mutex> lock(random_lock);
|
lock_guard<mutex> lock(random_lock);
|
||||||
ge_p3 point;
|
ge_p3 point;
|
||||||
random_scalar(sec);
|
|
||||||
|
secret_key rng;
|
||||||
|
|
||||||
|
if (recover)
|
||||||
|
{
|
||||||
|
rng = recovery_key;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
random_scalar(rng);
|
||||||
|
}
|
||||||
|
sec = rng;
|
||||||
|
sc_reduce32(&sec); // reduce in case second round of keys (sendkeys)
|
||||||
|
|
||||||
ge_scalarmult_base(&point, &sec);
|
ge_scalarmult_base(&point, &sec);
|
||||||
ge_p3_tobytes(&pub, &point);
|
ge_p3_tobytes(&pub, &point);
|
||||||
|
|
||||||
|
return rng;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool crypto_ops::check_key(const public_key &key) {
|
bool crypto_ops::check_key(const public_key &key) {
|
||||||
|
|
|
@ -62,8 +62,8 @@ namespace crypto {
|
||||||
void operator=(const crypto_ops &);
|
void operator=(const crypto_ops &);
|
||||||
~crypto_ops();
|
~crypto_ops();
|
||||||
|
|
||||||
static void generate_keys(public_key &, secret_key &);
|
static secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false);
|
||||||
friend void generate_keys(public_key &, secret_key &);
|
friend secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover);
|
||||||
static bool check_key(const public_key &);
|
static bool check_key(const public_key &);
|
||||||
friend bool check_key(const public_key &);
|
friend bool check_key(const public_key &);
|
||||||
static bool secret_key_to_public_key(const secret_key &, public_key &);
|
static bool secret_key_to_public_key(const secret_key &, public_key &);
|
||||||
|
@ -102,8 +102,8 @@ namespace crypto {
|
||||||
|
|
||||||
/* Generate a new key pair
|
/* Generate a new key pair
|
||||||
*/
|
*/
|
||||||
inline void generate_keys(public_key &pub, secret_key &sec) {
|
inline secret_key generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key = secret_key(), bool recover = false) {
|
||||||
crypto_ops::generate_keys(pub, sec);
|
return crypto_ops::generate_keys(pub, sec, recovery_key, recover);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check a public key. Returns true if it is valid, false otherwise.
|
/* Check a public key. Returns true if it is valid, false otherwise.
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
/*
|
||||||
|
* This file and its header file are for translating Electrum-style word lists
|
||||||
|
* into their equivalent byte representations for cross-compatibility with
|
||||||
|
* that method of "backing up" one's wallet keys.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <cassert>
|
||||||
|
#include <map>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
|
#include "crypto/crypto.h" // for declaration of crypto::secret_key
|
||||||
|
|
||||||
|
#include "crypto/electrum-words.h"
|
||||||
|
|
||||||
|
namespace crypto
|
||||||
|
{
|
||||||
|
namespace ElectrumWords
|
||||||
|
{
|
||||||
|
|
||||||
|
/* convert words to bytes, 3 words -> 4 bytes
|
||||||
|
* returns:
|
||||||
|
* false if not a multiple of 3 words, or if a words is not in the
|
||||||
|
* words list
|
||||||
|
*
|
||||||
|
* true otherwise
|
||||||
|
*/
|
||||||
|
bool words_to_bytes(const std::string& words, crypto::secret_key& dst)
|
||||||
|
{
|
||||||
|
int n = NUMWORDS; // hardcoded because this is what electrum uses
|
||||||
|
|
||||||
|
std::vector<std::string> wlist;
|
||||||
|
|
||||||
|
boost::split(wlist, words, boost::is_any_of(" "));
|
||||||
|
|
||||||
|
// error on non-compliant word list
|
||||||
|
if (wlist.size() != 12 && wlist.size() != 24) return false;
|
||||||
|
|
||||||
|
for (unsigned int i=0; i < wlist.size() / 3; i++)
|
||||||
|
{
|
||||||
|
uint32_t val;
|
||||||
|
uint32_t w1, w2, w3;
|
||||||
|
|
||||||
|
// verify all three words exist in the word list
|
||||||
|
if (wordsMap.count(wlist[i*3]) == 0 ||
|
||||||
|
wordsMap.count(wlist[i*3 + 1]) == 0 ||
|
||||||
|
wordsMap.count(wlist[i*3 + 2]) == 0)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
w1 = wordsMap.at(wlist[i*3]);
|
||||||
|
w2 = wordsMap.at(wlist[i*3 + 1]);
|
||||||
|
w3 = wordsMap.at(wlist[i*3 + 2]);
|
||||||
|
|
||||||
|
val = w1 + n * (((n - w1) + w2) % n) + n * n * (((n - w2) + w3) % n);
|
||||||
|
|
||||||
|
if (!(val % n == w1)) return false;
|
||||||
|
|
||||||
|
memcpy(dst.data + i * 4, &val, 4); // copy 4 bytes to position
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string wlist_copy = words;
|
||||||
|
if (wlist.size() == 12)
|
||||||
|
{
|
||||||
|
memcpy(dst.data, dst.data + 16, 16); // if electrum 12-word seed, duplicate
|
||||||
|
wlist_copy += ' ';
|
||||||
|
wlist_copy += words;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* convert bytes to words, 4 bytes-> 3 words
|
||||||
|
* returns:
|
||||||
|
* false if wrong number of bytes (shouldn't be possible)
|
||||||
|
* true otherwise
|
||||||
|
*/
|
||||||
|
bool bytes_to_words(const crypto::secret_key& src, std::string& words)
|
||||||
|
{
|
||||||
|
int n = NUMWORDS; // hardcoded because this is what electrum uses
|
||||||
|
|
||||||
|
if (sizeof(src.data) % 4 != 0) return false;
|
||||||
|
|
||||||
|
// 8 bytes -> 3 words. 8 digits base 16 -> 3 digits base 1626
|
||||||
|
for (unsigned int i=0; i < sizeof(src.data)/4; i++, words += ' ')
|
||||||
|
{
|
||||||
|
uint32_t w1, w2, w3;
|
||||||
|
|
||||||
|
uint32_t val;
|
||||||
|
|
||||||
|
memcpy(&val, (src.data) + (i * 4), 4);
|
||||||
|
|
||||||
|
w1 = val % n;
|
||||||
|
w2 = ((val / n) + w1) % n;
|
||||||
|
w3 = (((val / n) / n) + w2) % n;
|
||||||
|
|
||||||
|
words += wordsArray[w1];
|
||||||
|
words += ' ';
|
||||||
|
words += wordsArray[w2];
|
||||||
|
words += ' ';
|
||||||
|
words += wordsArray[w3];
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ElectrumWords
|
||||||
|
|
||||||
|
} // namespace crypto
|
File diff suppressed because it is too large
Load Diff
|
@ -39,9 +39,9 @@ extern "C" {
|
||||||
//#define OAES_HAVE_ISAAC 1
|
//#define OAES_HAVE_ISAAC 1
|
||||||
//#endif // OAES_HAVE_ISAAC
|
//#endif // OAES_HAVE_ISAAC
|
||||||
|
|
||||||
#ifndef OAES_DEBUG
|
//#ifndef OAES_DEBUG
|
||||||
#define OAES_DEBUG 0
|
//#define OAES_DEBUG 0
|
||||||
#endif // OAES_DEBUG
|
//#endif // OAES_DEBUG
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,31 +64,6 @@ static const char _NR[] = {
|
||||||
# define min(a,b) (((a)<(b)) ? (a) : (b))
|
# define min(a,b) (((a)<(b)) ? (a) : (b))
|
||||||
#endif /* min */
|
#endif /* min */
|
||||||
|
|
||||||
typedef struct _oaes_key
|
|
||||||
{
|
|
||||||
size_t data_len;
|
|
||||||
uint8_t *data;
|
|
||||||
size_t exp_data_len;
|
|
||||||
uint8_t *exp_data;
|
|
||||||
size_t num_keys;
|
|
||||||
size_t key_base;
|
|
||||||
} oaes_key;
|
|
||||||
|
|
||||||
typedef struct _oaes_ctx
|
|
||||||
{
|
|
||||||
#ifdef OAES_HAVE_ISAAC
|
|
||||||
randctx * rctx;
|
|
||||||
#endif // OAES_HAVE_ISAAC
|
|
||||||
|
|
||||||
#ifdef OAES_DEBUG
|
|
||||||
oaes_step_cb step_cb;
|
|
||||||
#endif // OAES_DEBUG
|
|
||||||
|
|
||||||
oaes_key * key;
|
|
||||||
OAES_OPTION options;
|
|
||||||
uint8_t iv[OAES_BLOCK_SIZE];
|
|
||||||
} oaes_ctx;
|
|
||||||
|
|
||||||
// "OAES<8-bit header version><8-bit type><16-bit options><8-bit flags><56-bit reserved>"
|
// "OAES<8-bit header version><8-bit type><16-bit options><8-bit flags><56-bit reserved>"
|
||||||
static uint8_t oaes_header[OAES_BLOCK_SIZE] = {
|
static uint8_t oaes_header[OAES_BLOCK_SIZE] = {
|
||||||
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f,
|
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f,
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#define _OAES_LIB_H
|
#define _OAES_LIB_H
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -101,6 +102,30 @@ typedef int ( * oaes_step_cb ) (
|
||||||
|
|
||||||
typedef uint16_t OAES_OPTION;
|
typedef uint16_t OAES_OPTION;
|
||||||
|
|
||||||
|
typedef struct _oaes_key
|
||||||
|
{
|
||||||
|
size_t data_len;
|
||||||
|
uint8_t *data;
|
||||||
|
size_t exp_data_len;
|
||||||
|
uint8_t *exp_data;
|
||||||
|
size_t num_keys;
|
||||||
|
size_t key_base;
|
||||||
|
} oaes_key;
|
||||||
|
|
||||||
|
typedef struct _oaes_ctx
|
||||||
|
{
|
||||||
|
#ifdef OAES_HAVE_ISAAC
|
||||||
|
randctx * rctx;
|
||||||
|
#endif // OAES_HAVE_ISAAC
|
||||||
|
|
||||||
|
#ifdef OAES_DEBUG
|
||||||
|
oaes_step_cb step_cb;
|
||||||
|
#endif // OAES_DEBUG
|
||||||
|
|
||||||
|
oaes_key * key;
|
||||||
|
OAES_OPTION options;
|
||||||
|
uint8_t iv[OAES_BLOCK_SIZE];
|
||||||
|
} oaes_ctx;
|
||||||
/*
|
/*
|
||||||
* // usage:
|
* // usage:
|
||||||
*
|
*
|
||||||
|
|
|
@ -11,143 +11,251 @@
|
||||||
#include "hash-ops.h"
|
#include "hash-ops.h"
|
||||||
#include "oaes_lib.h"
|
#include "oaes_lib.h"
|
||||||
|
|
||||||
static void (*const extra_hashes[4])(const void *, size_t, char *) = {
|
#include <emmintrin.h>
|
||||||
hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein
|
|
||||||
};
|
|
||||||
|
|
||||||
#define MEMORY (1 << 21) /* 2 MiB */
|
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||||
|
#include <intrin.h>
|
||||||
|
#define STATIC
|
||||||
|
#define INLINE __inline
|
||||||
|
#if !defined(RDATA_ALIGN16)
|
||||||
|
#define RDATA_ALIGN16 __declspec(align(16))
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
#include <wmmintrin.h>
|
||||||
|
#define STATIC static
|
||||||
|
#define INLINE inline
|
||||||
|
#if !defined(RDATA_ALIGN16)
|
||||||
|
#define RDATA_ALIGN16 __attribute__ ((aligned(16)))
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MEMORY (1 << 21) // 2MB scratchpad
|
||||||
#define ITER (1 << 20)
|
#define ITER (1 << 20)
|
||||||
#define AES_BLOCK_SIZE 16
|
#define AES_BLOCK_SIZE 16
|
||||||
#define AES_KEY_SIZE 32 /*16*/
|
#define AES_KEY_SIZE 32
|
||||||
#define INIT_SIZE_BLK 8
|
#define INIT_SIZE_BLK 8
|
||||||
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE)
|
#define INIT_SIZE_BYTE (INIT_SIZE_BLK * AES_BLOCK_SIZE)
|
||||||
|
|
||||||
static size_t e2i(const uint8_t* a, size_t count) { return (*((uint64_t*)a) / AES_BLOCK_SIZE) & (count - 1); }
|
#define U64(x) ((uint64_t *) (x))
|
||||||
|
#define R128(x) ((__m128i *) (x))
|
||||||
|
|
||||||
static void mul(const uint8_t* a, const uint8_t* b, uint8_t* res) {
|
extern int aesb_single_round(const uint8_t *in, uint8_t*out, const uint8_t *expandedKey);
|
||||||
uint64_t a0, b0;
|
extern int aesb_pseudo_round(const uint8_t *in, uint8_t *out, const uint8_t *expandedKey);
|
||||||
uint64_t hi, lo;
|
|
||||||
|
|
||||||
a0 = SWAP64LE(((uint64_t*)a)[0]);
|
|
||||||
b0 = SWAP64LE(((uint64_t*)b)[0]);
|
|
||||||
lo = mul128(a0, b0, &hi);
|
|
||||||
((uint64_t*)res)[0] = SWAP64LE(hi);
|
|
||||||
((uint64_t*)res)[1] = SWAP64LE(lo);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void sum_half_blocks(uint8_t* a, const uint8_t* b) {
|
|
||||||
uint64_t a0, a1, b0, b1;
|
|
||||||
|
|
||||||
a0 = SWAP64LE(((uint64_t*)a)[0]);
|
|
||||||
a1 = SWAP64LE(((uint64_t*)a)[1]);
|
|
||||||
b0 = SWAP64LE(((uint64_t*)b)[0]);
|
|
||||||
b1 = SWAP64LE(((uint64_t*)b)[1]);
|
|
||||||
a0 += b0;
|
|
||||||
a1 += b1;
|
|
||||||
((uint64_t*)a)[0] = SWAP64LE(a0);
|
|
||||||
((uint64_t*)a)[1] = SWAP64LE(a1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void copy_block(uint8_t* dst, const uint8_t* src) {
|
|
||||||
memcpy(dst, src, AES_BLOCK_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void swap_blocks(uint8_t* a, uint8_t* b) {
|
|
||||||
size_t i;
|
|
||||||
uint8_t t;
|
|
||||||
for (i = 0; i < AES_BLOCK_SIZE; i++) {
|
|
||||||
t = a[i];
|
|
||||||
a[i] = b[i];
|
|
||||||
b[i] = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void xor_blocks(uint8_t* a, const uint8_t* b) {
|
|
||||||
size_t i;
|
|
||||||
for (i = 0; i < AES_BLOCK_SIZE; i++) {
|
|
||||||
a[i] ^= b[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
union cn_slow_hash_state {
|
union cn_slow_hash_state
|
||||||
union hash_state hs;
|
{
|
||||||
struct {
|
union hash_state hs;
|
||||||
uint8_t k[64];
|
struct
|
||||||
uint8_t init[INIT_SIZE_BYTE];
|
{
|
||||||
};
|
uint8_t k[64];
|
||||||
|
uint8_t init[INIT_SIZE_BYTE];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
void cn_slow_hash(const void *data, size_t length, char *hash) {
|
#if defined(_MSC_VER) || defined(__INTEL_COMPILER)
|
||||||
uint8_t long_state[MEMORY];
|
#define cpuid(info,x) __cpuidex(info,x,0)
|
||||||
union cn_slow_hash_state state;
|
#else
|
||||||
uint8_t text[INIT_SIZE_BYTE];
|
void cpuid(int CPUInfo[4], int InfoType)
|
||||||
uint8_t a[AES_BLOCK_SIZE];
|
{
|
||||||
uint8_t b[AES_BLOCK_SIZE];
|
__asm__ __volatile__
|
||||||
uint8_t c[AES_BLOCK_SIZE];
|
(
|
||||||
uint8_t d[AES_BLOCK_SIZE];
|
"cpuid":
|
||||||
size_t i, j;
|
"=a" (CPUInfo[0]),
|
||||||
uint8_t aes_key[AES_KEY_SIZE];
|
"=b" (CPUInfo[1]),
|
||||||
OAES_CTX* aes_ctx;
|
"=c" (CPUInfo[2]),
|
||||||
|
"=d" (CPUInfo[3]) :
|
||||||
hash_process(&state.hs, data, length);
|
"a" (InfoType), "c" (0)
|
||||||
memcpy(text, state.init, INIT_SIZE_BYTE);
|
);
|
||||||
memcpy(aes_key, state.hs.b, AES_KEY_SIZE);
|
}
|
||||||
aes_ctx = oaes_alloc();
|
#endif
|
||||||
for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) {
|
|
||||||
for (j = 0; j < INIT_SIZE_BLK; j++) {
|
STATIC INLINE void mul(const uint8_t *a, const uint8_t *b, uint8_t *res)
|
||||||
oaes_key_import_data(aes_ctx, aes_key, AES_KEY_SIZE);
|
{
|
||||||
oaes_pseudo_encrypt_ecb(aes_ctx, &text[AES_BLOCK_SIZE * j]);
|
uint64_t a0, b0;
|
||||||
/*memcpy(aes_key, &text[AES_BLOCK_SIZE * j], AES_KEY_SIZE);*/
|
uint64_t hi, lo;
|
||||||
memcpy(aes_key, state.hs.b, AES_KEY_SIZE);
|
|
||||||
}
|
a0 = U64(a)[0];
|
||||||
memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
b0 = U64(b)[0];
|
||||||
}
|
lo = mul128(a0, b0, &hi);
|
||||||
|
U64(res)[0] = hi;
|
||||||
for (i = 0; i < 16; i++) {
|
U64(res)[1] = lo;
|
||||||
a[i] = state.k[ i] ^ state.k[32 + i];
|
}
|
||||||
b[i] = state.k[16 + i] ^ state.k[48 + i];
|
|
||||||
}
|
STATIC INLINE void sum_half_blocks(uint8_t *a, const uint8_t *b)
|
||||||
|
{
|
||||||
for (i = 0; i < ITER / 2; i++) {
|
uint64_t a0, a1, b0, b1;
|
||||||
/* Dependency chain: address -> read value ------+
|
a0 = U64(a)[0];
|
||||||
* written value <-+ hard function (AES or MUL) <+
|
a1 = U64(a)[1];
|
||||||
* next address <-+
|
b0 = U64(b)[0];
|
||||||
*/
|
b1 = U64(b)[1];
|
||||||
/* Iteration 1 */
|
a0 += b0;
|
||||||
j = e2i(a, MEMORY / AES_BLOCK_SIZE);
|
a1 += b1;
|
||||||
copy_block(c, &long_state[j * AES_BLOCK_SIZE]);
|
U64(a)[0] = a0;
|
||||||
oaes_encryption_round(a, c);
|
U64(a)[1] = a1;
|
||||||
xor_blocks(b, c);
|
}
|
||||||
swap_blocks(b, c);
|
|
||||||
copy_block(&long_state[j * AES_BLOCK_SIZE], c);
|
STATIC INLINE void swap_blocks(uint8_t *a, uint8_t *b)
|
||||||
assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE));
|
{
|
||||||
swap_blocks(a, b);
|
uint64_t t[2];
|
||||||
/* Iteration 2 */
|
U64(t)[0] = U64(a)[0];
|
||||||
j = e2i(a, MEMORY / AES_BLOCK_SIZE);
|
U64(t)[1] = U64(a)[1];
|
||||||
copy_block(c, &long_state[j * AES_BLOCK_SIZE]);
|
U64(a)[0] = U64(b)[0];
|
||||||
mul(a, c, d);
|
U64(a)[1] = U64(b)[1];
|
||||||
sum_half_blocks(b, d);
|
U64(b)[0] = U64(t)[0];
|
||||||
swap_blocks(b, c);
|
U64(b)[1] = U64(t)[1];
|
||||||
xor_blocks(b, c);
|
}
|
||||||
copy_block(&long_state[j * AES_BLOCK_SIZE], c);
|
|
||||||
assert(j == e2i(a, MEMORY / AES_BLOCK_SIZE));
|
STATIC INLINE void xor_blocks(uint8_t *a, const uint8_t *b)
|
||||||
swap_blocks(a, b);
|
{
|
||||||
}
|
U64(a)[0] ^= U64(b)[0];
|
||||||
|
U64(a)[1] ^= U64(b)[1];
|
||||||
memcpy(text, state.init, INIT_SIZE_BYTE);
|
}
|
||||||
for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) {
|
|
||||||
for (j = 0; j < INIT_SIZE_BLK; j++) {
|
STATIC INLINE int check_aes_hw(void)
|
||||||
/*oaes_key_import_data(aes_ctx, &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE], AES_KEY_SIZE);*/
|
{
|
||||||
oaes_key_import_data(aes_ctx, &state.hs.b[32], AES_KEY_SIZE);
|
int cpuid_results[4];
|
||||||
xor_blocks(&text[j * AES_BLOCK_SIZE], &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
|
static int supported = -1;
|
||||||
oaes_pseudo_encrypt_ecb(aes_ctx, &text[j * AES_BLOCK_SIZE]);
|
|
||||||
}
|
if(supported >= 0)
|
||||||
}
|
return supported;
|
||||||
memcpy(state.init, text, INIT_SIZE_BYTE);
|
|
||||||
hash_permutation(&state.hs);
|
cpuid(cpuid_results,1);
|
||||||
/*memcpy(hash, &state, 32);*/
|
return supported = cpuid_results[2] & (1 << 25);
|
||||||
extra_hashes[state.hs.b[0] & 3](&state, 200, hash);
|
}
|
||||||
oaes_free(&aes_ctx);
|
|
||||||
|
STATIC INLINE void aesni_pseudo_round(const uint8_t *in, uint8_t *out,
|
||||||
|
const uint8_t *expandedKey)
|
||||||
|
{
|
||||||
|
__m128i *k = R128(expandedKey);
|
||||||
|
__m128i d;
|
||||||
|
|
||||||
|
d = _mm_loadu_si128(R128(in));
|
||||||
|
d = _mm_aesenc_si128(d, *R128(&k[0]));
|
||||||
|
d = _mm_aesenc_si128(d, *R128(&k[1]));
|
||||||
|
d = _mm_aesenc_si128(d, *R128(&k[2]));
|
||||||
|
d = _mm_aesenc_si128(d, *R128(&k[3]));
|
||||||
|
d = _mm_aesenc_si128(d, *R128(&k[4]));
|
||||||
|
d = _mm_aesenc_si128(d, *R128(&k[5]));
|
||||||
|
d = _mm_aesenc_si128(d, *R128(&k[6]));
|
||||||
|
d = _mm_aesenc_si128(d, *R128(&k[7]));
|
||||||
|
d = _mm_aesenc_si128(d, *R128(&k[8]));
|
||||||
|
d = _mm_aesenc_si128(d, *R128(&k[9]));
|
||||||
|
_mm_storeu_si128((R128(out)), d);
|
||||||
|
}
|
||||||
|
|
||||||
|
void cn_slow_hash(const void *data, size_t length, char *hash)
|
||||||
|
{
|
||||||
|
uint8_t long_state[MEMORY];
|
||||||
|
uint8_t text[INIT_SIZE_BYTE];
|
||||||
|
uint8_t a[AES_BLOCK_SIZE];
|
||||||
|
uint8_t b[AES_BLOCK_SIZE];
|
||||||
|
uint8_t d[AES_BLOCK_SIZE];
|
||||||
|
uint8_t aes_key[AES_KEY_SIZE];
|
||||||
|
RDATA_ALIGN16 uint8_t expandedKey[256];
|
||||||
|
|
||||||
|
union cn_slow_hash_state state;
|
||||||
|
|
||||||
|
size_t i, j;
|
||||||
|
uint8_t *p = NULL;
|
||||||
|
oaes_ctx *aes_ctx;
|
||||||
|
|
||||||
|
int useAes = check_aes_hw();
|
||||||
|
static void (*const extra_hashes[4])(const void *, size_t, char *) =
|
||||||
|
{
|
||||||
|
hash_extra_blake, hash_extra_groestl, hash_extra_jh, hash_extra_skein
|
||||||
|
};
|
||||||
|
|
||||||
|
hash_process(&state.hs, data, length);
|
||||||
|
memcpy(text, state.init, INIT_SIZE_BYTE);
|
||||||
|
|
||||||
|
aes_ctx = (oaes_ctx *) oaes_alloc();
|
||||||
|
oaes_key_import_data(aes_ctx, state.hs.b, AES_KEY_SIZE);
|
||||||
|
|
||||||
|
// use aligned data
|
||||||
|
memcpy(expandedKey, aes_ctx->key->exp_data, aes_ctx->key->exp_data_len);
|
||||||
|
|
||||||
|
if(useAes)
|
||||||
|
{
|
||||||
|
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||||
|
{
|
||||||
|
for(j = 0; j < INIT_SIZE_BLK; j++)
|
||||||
|
aesni_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], expandedKey);
|
||||||
|
memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||||
|
{
|
||||||
|
for(j = 0; j < INIT_SIZE_BLK; j++)
|
||||||
|
aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], expandedKey);
|
||||||
|
|
||||||
|
memcpy(&long_state[i * INIT_SIZE_BYTE], text, INIT_SIZE_BYTE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
U64(a)[0] = U64(&state.k[0])[0] ^ U64(&state.k[32])[0];
|
||||||
|
U64(a)[1] = U64(&state.k[0])[1] ^ U64(&state.k[32])[1];
|
||||||
|
U64(b)[0] = U64(&state.k[16])[0] ^ U64(&state.k[48])[0];
|
||||||
|
U64(b)[1] = U64(&state.k[16])[1] ^ U64(&state.k[48])[1];
|
||||||
|
|
||||||
|
for(i = 0; i < ITER / 2; i++)
|
||||||
|
{
|
||||||
|
#define TOTALBLOCKS (MEMORY / AES_BLOCK_SIZE)
|
||||||
|
#define state_index(x) (((*((uint64_t *)x) >> 4) & (TOTALBLOCKS - 1)) << 4)
|
||||||
|
|
||||||
|
// Iteration 1
|
||||||
|
p = &long_state[state_index(a)];
|
||||||
|
|
||||||
|
if(useAes)
|
||||||
|
_mm_storeu_si128(R128(p), _mm_aesenc_si128(_mm_loadu_si128(R128(p)), _mm_loadu_si128(R128(a))));
|
||||||
|
else
|
||||||
|
aesb_single_round(p, p, a);
|
||||||
|
|
||||||
|
xor_blocks(b, p);
|
||||||
|
swap_blocks(b, p);
|
||||||
|
swap_blocks(a, b);
|
||||||
|
|
||||||
|
// Iteration 2
|
||||||
|
p = &long_state[state_index(a)];
|
||||||
|
|
||||||
|
mul(a, p, d);
|
||||||
|
sum_half_blocks(b, d);
|
||||||
|
swap_blocks(b, p);
|
||||||
|
xor_blocks(b, p);
|
||||||
|
swap_blocks(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(text, state.init, INIT_SIZE_BYTE);
|
||||||
|
oaes_key_import_data(aes_ctx, &state.hs.b[32], AES_KEY_SIZE);
|
||||||
|
memcpy(expandedKey, aes_ctx->key->exp_data, aes_ctx->key->exp_data_len);
|
||||||
|
if(useAes)
|
||||||
|
{
|
||||||
|
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||||
|
{
|
||||||
|
for(j = 0; j < INIT_SIZE_BLK; j++)
|
||||||
|
{
|
||||||
|
xor_blocks(&text[j * AES_BLOCK_SIZE], &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
|
||||||
|
aesni_pseudo_round(&text[j * AES_BLOCK_SIZE], &text[j * AES_BLOCK_SIZE], expandedKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(i = 0; i < MEMORY / INIT_SIZE_BYTE; i++)
|
||||||
|
{
|
||||||
|
for(j = 0; j < INIT_SIZE_BLK; j++)
|
||||||
|
{
|
||||||
|
xor_blocks(&text[j * AES_BLOCK_SIZE], &long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
|
||||||
|
aesb_pseudo_round(&text[AES_BLOCK_SIZE * j], &text[AES_BLOCK_SIZE * j], expandedKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
oaes_free((OAES_CTX **) &aes_ctx);
|
||||||
|
memcpy(state.init, text, INIT_SIZE_BYTE);
|
||||||
|
hash_permutation(&state.hs);
|
||||||
|
extra_hashes[state.hs.b[0] & 3](&state, 200, hash);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
#define CRYPTONOTE_MAX_BLOCK_SIZE 500000000 // block header blob limit, never used!
|
#define CRYPTONOTE_MAX_BLOCK_SIZE 500000000 // block header blob limit, never used!
|
||||||
#define CRYPTONOTE_MAX_TX_SIZE 1000000000
|
#define CRYPTONOTE_MAX_TX_SIZE 1000000000
|
||||||
#define CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER 0
|
#define CRYPTONOTE_PUBLIC_ADDRESS_TEXTBLOB_VER 0
|
||||||
#define CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX 18 // addresses start with "2"
|
#define CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX 18 // addresses start with "4"
|
||||||
#define CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW 60
|
#define CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW 60
|
||||||
#define CURRENT_TRANSACTION_VERSION 1
|
#define CURRENT_TRANSACTION_VERSION 1
|
||||||
#define CURRENT_BLOCK_MAJOR_VERSION 1
|
#define CURRENT_BLOCK_MAJOR_VERSION 1
|
||||||
|
@ -26,8 +26,8 @@
|
||||||
#define CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE 600
|
#define CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE 600
|
||||||
#define CRYPTONOTE_DISPLAY_DECIMAL_POINT 12
|
#define CRYPTONOTE_DISPLAY_DECIMAL_POINT 12
|
||||||
// COIN - number of smallest units in one coin
|
// COIN - number of smallest units in one coin
|
||||||
#define COIN ((uint64_t)100000000) // pow(10, 8)
|
#define COIN ((uint64_t)1000000000000) // pow(10, 12)
|
||||||
#define DEFAULT_FEE ((uint64_t)1000000) // pow(10, 6)
|
#define DEFAULT_FEE ((uint64_t)5000000000) // 5 * pow(10, 9)
|
||||||
|
|
||||||
|
|
||||||
#define ORPHANED_BLOCKS_MAX_COUNT 100
|
#define ORPHANED_BLOCKS_MAX_COUNT 100
|
||||||
|
@ -51,6 +51,8 @@
|
||||||
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT 200 //by default, blocks count in blocks downloading
|
#define BLOCKS_SYNCHRONIZING_DEFAULT_COUNT 200 //by default, blocks count in blocks downloading
|
||||||
#define CRYPTONOTE_PROTOCOL_HOP_RELAX_COUNT 3 //value of hop, after which we use only announce of new block
|
#define CRYPTONOTE_PROTOCOL_HOP_RELAX_COUNT 3 //value of hop, after which we use only announce of new block
|
||||||
|
|
||||||
|
#define CRYPTONOTE_MEMPOOL_TX_LIVETIME 86400 //seconds, one day
|
||||||
|
#define CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME 604800 //seconds, one week
|
||||||
|
|
||||||
#define P2P_DEFAULT_PORT 18080
|
#define P2P_DEFAULT_PORT 18080
|
||||||
#define RPC_DEFAULT_PORT 18081
|
#define RPC_DEFAULT_PORT 18081
|
||||||
|
|
|
@ -10,6 +10,10 @@
|
||||||
#include "account.h"
|
#include "account.h"
|
||||||
#include "warnings.h"
|
#include "warnings.h"
|
||||||
#include "crypto/crypto.h"
|
#include "crypto/crypto.h"
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "crypto/keccak.h"
|
||||||
|
}
|
||||||
#include "cryptonote_core/cryptonote_basic_impl.h"
|
#include "cryptonote_core/cryptonote_basic_impl.h"
|
||||||
#include "cryptonote_core/cryptonote_format_utils.h"
|
#include "cryptonote_core/cryptonote_format_utils.h"
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
@ -29,11 +33,17 @@ DISABLE_VS_WARNINGS(4244 4345)
|
||||||
m_keys = account_keys();
|
m_keys = account_keys();
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
void account_base::generate()
|
crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover, bool two_random)
|
||||||
{
|
{
|
||||||
generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key);
|
crypto::secret_key first = generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key, recovery_key, recover);
|
||||||
generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_secret_key);
|
|
||||||
|
// rng for generating second set of keys is hash of first rng. means only one set of electrum-style words needed for recovery
|
||||||
|
crypto::secret_key second;
|
||||||
|
keccak((uint8_t *)&first, sizeof(crypto::secret_key), (uint8_t *)&second, sizeof(crypto::secret_key));
|
||||||
|
|
||||||
|
generate_keys(m_keys.m_account_address.m_view_public_key, m_keys.m_view_secret_key, second, two_random ? false : true);
|
||||||
m_creation_timestamp = time(NULL);
|
m_creation_timestamp = time(NULL);
|
||||||
|
return first;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------
|
//-----------------------------------------------------------------
|
||||||
const account_keys& account_base::get_keys() const
|
const account_keys& account_base::get_keys() const
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace cryptonote
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
account_base();
|
account_base();
|
||||||
void generate();
|
crypto::secret_key generate(const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false, bool two_random = false);
|
||||||
const account_keys& get_keys() const;
|
const account_keys& get_keys() const;
|
||||||
std::string get_public_address_str();
|
std::string get_public_address_str();
|
||||||
|
|
||||||
|
|
|
@ -372,7 +372,7 @@ bool blockchain_storage::rollback_blockchain_switching(std::list<block>& origina
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
bool blockchain_storage::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::iterator>& alt_chain)
|
bool blockchain_storage::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::iterator>& alt_chain, bool discard_disconnected_chain)
|
||||||
{
|
{
|
||||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||||
CHECK_AND_ASSERT_MES(alt_chain.size(), false, "switch_to_alternative_blockchain: empty chain passed");
|
CHECK_AND_ASSERT_MES(alt_chain.size(), false, "switch_to_alternative_blockchain: empty chain passed");
|
||||||
|
@ -414,16 +414,19 @@ bool blockchain_storage::switch_to_alternative_blockchain(std::list<blocks_ext_b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//pushing old chain as alternative chain
|
if(!discard_disconnected_chain)
|
||||||
BOOST_FOREACH(auto& old_ch_ent, disconnected_chain)
|
|
||||||
{
|
{
|
||||||
block_verification_context bvc = boost::value_initialized<block_verification_context>();
|
//pushing old chain as alternative chain
|
||||||
bool r = handle_alternative_block(old_ch_ent, get_block_hash(old_ch_ent), bvc);
|
BOOST_FOREACH(auto& old_ch_ent, disconnected_chain)
|
||||||
if(!r)
|
|
||||||
{
|
{
|
||||||
LOG_ERROR("Failed to push ex-main chain blocks to alternative chain ");
|
block_verification_context bvc = boost::value_initialized<block_verification_context>();
|
||||||
rollback_blockchain_switching(disconnected_chain, split_height);
|
bool r = handle_alternative_block(old_ch_ent, get_block_hash(old_ch_ent), bvc);
|
||||||
return false;
|
if(!r)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Failed to push ex-main chain blocks to alternative chain ");
|
||||||
|
rollback_blockchain_switching(disconnected_chain, split_height);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -701,6 +704,22 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
|
||||||
{
|
{
|
||||||
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
||||||
|
|
||||||
|
uint64_t block_height = get_block_height(b);
|
||||||
|
if(0 == block_height)
|
||||||
|
{
|
||||||
|
LOG_ERROR("Block with id: " << string_tools::pod_to_hex(id) << " (as alternative) have wrong miner transaction");
|
||||||
|
bvc.m_verifivation_failed = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!m_checkpoints.is_alternative_block_allowed(get_current_blockchain_height(), block_height))
|
||||||
|
{
|
||||||
|
LOG_PRINT_RED_L0("Block with id: " << id
|
||||||
|
<< ENDL << " can't be accepted for alternative chain, block height: " << block_height
|
||||||
|
<< ENDL << " blockchain height: " << get_current_blockchain_height());
|
||||||
|
bvc.m_verifivation_failed = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//block is not related with head of main chain
|
//block is not related with head of main chain
|
||||||
//first of all - look in alternative chains container
|
//first of all - look in alternative chains container
|
||||||
auto it_main_prev = m_blocks_index.find(b.prev_id);
|
auto it_main_prev = m_blocks_index.find(b.prev_id);
|
||||||
|
@ -746,31 +765,28 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
|
||||||
block_extended_info bei = boost::value_initialized<block_extended_info>();
|
block_extended_info bei = boost::value_initialized<block_extended_info>();
|
||||||
bei.bl = b;
|
bei.bl = b;
|
||||||
bei.height = alt_chain.size() ? it_prev->second.height + 1 : it_main_prev->second + 1;
|
bei.height = alt_chain.size() ? it_prev->second.height + 1 : it_main_prev->second + 1;
|
||||||
|
|
||||||
|
bool is_a_checkpoint;
|
||||||
|
if(!m_checkpoints.check_block(bei.height, id, is_a_checkpoint))
|
||||||
|
{
|
||||||
|
LOG_ERROR("CHECKPOINT VALIDATION FAILED");
|
||||||
|
bvc.m_verifivation_failed = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Always check PoW for alternative blocks
|
||||||
|
m_is_in_checkpoint_zone = false;
|
||||||
difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei);
|
difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei);
|
||||||
CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!");
|
CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!");
|
||||||
crypto::hash proof_of_work = null_hash;
|
crypto::hash proof_of_work = null_hash;
|
||||||
if(!m_checkpoints.is_in_checkpoint_zone(bei.height))
|
get_block_longhash(bei.bl, proof_of_work, bei.height);
|
||||||
|
if(!check_hash(proof_of_work, current_diff))
|
||||||
{
|
{
|
||||||
m_is_in_checkpoint_zone = false;
|
LOG_PRINT_RED_L0("Block with id: " << id
|
||||||
get_block_longhash(bei.bl, proof_of_work, bei.height);
|
<< ENDL << " for alternative chain, have not enough proof of work: " << proof_of_work
|
||||||
|
<< ENDL << " expected difficulty: " << current_diff);
|
||||||
if(!check_hash(proof_of_work, current_diff))
|
bvc.m_verifivation_failed = true;
|
||||||
{
|
return false;
|
||||||
LOG_PRINT_RED_L0("Block with id: " << id
|
|
||||||
<< ENDL << " for alternative chain, have not enough proof of work: " << proof_of_work
|
|
||||||
<< ENDL << " expected difficulty: " << current_diff);
|
|
||||||
bvc.m_verifivation_failed = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}else
|
|
||||||
{
|
|
||||||
m_is_in_checkpoint_zone = true;
|
|
||||||
if(!m_checkpoints.check_block(bei.height, id))
|
|
||||||
{
|
|
||||||
LOG_ERROR("CHECKPOINT VALIDATION FAILED");
|
|
||||||
bvc.m_verifivation_failed = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!prevalidate_miner_transaction(b, bei.height))
|
if(!prevalidate_miner_transaction(b, bei.height))
|
||||||
|
@ -792,22 +808,33 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
|
||||||
auto i_res = m_alternative_chains.insert(blocks_ext_by_hash::value_type(id, bei));
|
auto i_res = m_alternative_chains.insert(blocks_ext_by_hash::value_type(id, bei));
|
||||||
CHECK_AND_ASSERT_MES(i_res.second, false, "insertion of new alternative block returned as it already exist");
|
CHECK_AND_ASSERT_MES(i_res.second, false, "insertion of new alternative block returned as it already exist");
|
||||||
alt_chain.push_back(i_res.first);
|
alt_chain.push_back(i_res.first);
|
||||||
//check if difficulty bigger then in main chain
|
|
||||||
if(m_blocks.back().cumulative_difficulty < bei.cumulative_difficulty)
|
if(is_a_checkpoint)
|
||||||
{
|
{
|
||||||
//do reorganize!
|
//do reorganize!
|
||||||
LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_blocks.size() -1 << " with cum_difficulty " << m_blocks.back().cumulative_difficulty
|
LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_blocks.size() - 1 <<
|
||||||
<< ENDL << " alternative blockchain size: " << alt_chain.size() << " with cum_difficulty " << bei.cumulative_difficulty, LOG_LEVEL_0);
|
", checkpoint is found in alternative chain on height " << bei.height, LOG_LEVEL_0);
|
||||||
bool r = switch_to_alternative_blockchain(alt_chain);
|
bool r = switch_to_alternative_blockchain(alt_chain, true);
|
||||||
if(r) bvc.m_added_to_main_chain = true;
|
if(r) bvc.m_added_to_main_chain = true;
|
||||||
else bvc.m_verifivation_failed = true;
|
else bvc.m_verifivation_failed = true;
|
||||||
return r;
|
return r;
|
||||||
|
}else if(m_blocks.back().cumulative_difficulty < bei.cumulative_difficulty) //check if difficulty bigger then in main chain
|
||||||
|
{
|
||||||
|
//do reorganize!
|
||||||
|
LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_blocks.size() - 1 << " with cum_difficulty " << m_blocks.back().cumulative_difficulty
|
||||||
|
<< ENDL << " alternative blockchain size: " << alt_chain.size() << " with cum_difficulty " << bei.cumulative_difficulty, LOG_LEVEL_0);
|
||||||
|
bool r = switch_to_alternative_blockchain(alt_chain, false);
|
||||||
|
if(r) bvc.m_added_to_main_chain = true;
|
||||||
|
else bvc.m_verifivation_failed = true;
|
||||||
|
return r;
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
LOG_PRINT_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT " << bei.height
|
||||||
|
<< ENDL << "id:\t" << id
|
||||||
|
<< ENDL << "PoW:\t" << proof_of_work
|
||||||
|
<< ENDL << "difficulty:\t" << current_diff, LOG_LEVEL_0);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
LOG_PRINT_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT " << bei.height
|
|
||||||
<< ENDL << "id:\t" << id
|
|
||||||
<< ENDL << "PoW:\t" << proof_of_work
|
|
||||||
<< ENDL << "difficulty:\t" << current_diff, LOG_LEVEL_0);
|
|
||||||
return true;
|
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
//block orphaned
|
//block orphaned
|
||||||
|
@ -815,7 +842,6 @@ bool blockchain_storage::handle_alternative_block(const block& b, const crypto::
|
||||||
LOG_PRINT_RED_L0("Block recognized as orphaned and rejected, id = " << id);
|
LOG_PRINT_RED_L0("Block recognized as orphaned and rejected, id = " << id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------
|
//------------------------------------------------------------------
|
||||||
|
@ -1480,19 +1506,27 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
||||||
TIME_MEASURE_FINISH(target_calculating_time);
|
TIME_MEASURE_FINISH(target_calculating_time);
|
||||||
TIME_MEASURE_START(longhash_calculating_time);
|
TIME_MEASURE_START(longhash_calculating_time);
|
||||||
crypto::hash proof_of_work = null_hash;
|
crypto::hash proof_of_work = null_hash;
|
||||||
if(!m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height()))
|
|
||||||
{
|
|
||||||
proof_of_work = get_block_longhash(bl, m_blocks.size());
|
|
||||||
|
|
||||||
if(!check_hash(proof_of_work, current_diffic))
|
// Formerly the code below contained an if loop with the following condition
|
||||||
{
|
// !m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height())
|
||||||
LOG_PRINT_L0("Block with id: " << id << ENDL
|
// however, this caused the daemon to not bother checking PoW for blocks
|
||||||
<< "have not enough proof of work: " << proof_of_work << ENDL
|
// before checkpoints, which is very dangerous behaviour. We moved the PoW
|
||||||
<< "nexpected difficulty: " << current_diffic );
|
// validation out of the next chunk of code to make sure that we correctly
|
||||||
bvc.m_verifivation_failed = true;
|
// check PoW now.
|
||||||
return false;
|
proof_of_work = get_block_longhash(bl, m_blocks.size());
|
||||||
}
|
|
||||||
}else
|
if(!check_hash(proof_of_work, current_diffic))
|
||||||
|
{
|
||||||
|
LOG_PRINT_L0("Block with id: " << id << ENDL
|
||||||
|
<< "have not enough proof of work: " << proof_of_work << ENDL
|
||||||
|
<< "nexpected difficulty: " << current_diffic );
|
||||||
|
bvc.m_verifivation_failed = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we're at a checkpoint, ensure that our hardcoded checkpoint hash
|
||||||
|
// is correct.
|
||||||
|
if(m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height()))
|
||||||
{
|
{
|
||||||
if(!m_checkpoints.check_block(get_current_blockchain_height(), id))
|
if(!m_checkpoints.check_block(get_current_blockchain_height(), id))
|
||||||
{
|
{
|
||||||
|
@ -1501,6 +1535,7 @@ bool blockchain_storage::handle_block_to_main_chain(const block& bl, const crypt
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TIME_MEASURE_FINISH(longhash_calculating_time);
|
TIME_MEASURE_FINISH(longhash_calculating_time);
|
||||||
|
|
||||||
if(!prevalidate_miner_transaction(bl, m_blocks.size()))
|
if(!prevalidate_miner_transaction(bl, m_blocks.size()))
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
#include <boost/foreach.hpp>
|
#include <boost/foreach.hpp>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
|
|
||||||
|
#include "syncobj.h"
|
||||||
|
#include "string_tools.h"
|
||||||
#include "tx_pool.h"
|
#include "tx_pool.h"
|
||||||
#include "cryptonote_basic.h"
|
#include "cryptonote_basic.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
@ -50,7 +52,7 @@ namespace cryptonote
|
||||||
uint64_t already_generated_coins;
|
uint64_t already_generated_coins;
|
||||||
};
|
};
|
||||||
|
|
||||||
blockchain_storage(tx_memory_pool& tx_pool):m_tx_pool(tx_pool), m_current_block_cumul_sz_limit(0), m_is_in_checkpoint_zone(false)
|
blockchain_storage(tx_memory_pool& tx_pool):m_tx_pool(tx_pool), m_current_block_cumul_sz_limit(0), m_is_in_checkpoint_zone(false), m_is_blockchain_storing(false)
|
||||||
{};
|
{};
|
||||||
|
|
||||||
bool init() { return init(tools::get_default_data_dir()); }
|
bool init() { return init(tools::get_default_data_dir()); }
|
||||||
|
@ -119,7 +121,7 @@ namespace cryptonote
|
||||||
missed_bs.push_back(bl_id);
|
missed_bs.push_back(bl_id);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CHECK_AND_ASSERT_MES(it->second < m_blocks.size(), false, "Internal error: bl_id=" << string_tools::pod_to_hex(bl_id)
|
CHECK_AND_ASSERT_MES(it->second < m_blocks.size(), false, "Internal error: bl_id=" << epee::string_tools::pod_to_hex(bl_id)
|
||||||
<< " have index record with offset="<<it->second<< ", bigger then m_blocks.size()=" << m_blocks.size());
|
<< " have index record with offset="<<it->second<< ", bigger then m_blocks.size()=" << m_blocks.size());
|
||||||
blocks.push_back(m_blocks[it->second].bl);
|
blocks.push_back(m_blocks[it->second].bl);
|
||||||
}
|
}
|
||||||
|
@ -163,7 +165,7 @@ namespace cryptonote
|
||||||
typedef std::map<uint64_t, std::vector<std::pair<crypto::hash, size_t>>> outputs_container; //crypto::hash - tx hash, size_t - index of out in transaction
|
typedef std::map<uint64_t, std::vector<std::pair<crypto::hash, size_t>>> outputs_container; //crypto::hash - tx hash, size_t - index of out in transaction
|
||||||
|
|
||||||
tx_memory_pool& m_tx_pool;
|
tx_memory_pool& m_tx_pool;
|
||||||
critical_section m_blockchain_lock; // TODO: add here reader/writer lock
|
epee::critical_section m_blockchain_lock; // TODO: add here reader/writer lock
|
||||||
|
|
||||||
// main chain
|
// main chain
|
||||||
blocks_container m_blocks; // height -> block_extended_info
|
blocks_container m_blocks; // height -> block_extended_info
|
||||||
|
@ -186,7 +188,7 @@ namespace cryptonote
|
||||||
std::atomic<bool> m_is_in_checkpoint_zone;
|
std::atomic<bool> m_is_in_checkpoint_zone;
|
||||||
std::atomic<bool> m_is_blockchain_storing;
|
std::atomic<bool> m_is_blockchain_storing;
|
||||||
|
|
||||||
bool switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::iterator>& alt_chain);
|
bool switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::iterator>& alt_chain, bool discard_disconnected_chain);
|
||||||
bool pop_block_from_blockchain();
|
bool pop_block_from_blockchain();
|
||||||
bool purge_block_data_from_blockchain(const block& b, size_t processed_tx_count);
|
bool purge_block_data_from_blockchain(const block& b, size_t processed_tx_count);
|
||||||
bool purge_transaction_from_blockchain(const crypto::hash& tx_id);
|
bool purge_transaction_from_blockchain(const crypto::hash& tx_id);
|
||||||
|
@ -301,7 +303,7 @@ namespace cryptonote
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
transactions_container::iterator tx_it = m_transactions.find(amount_outs_vec[i].first);
|
transactions_container::iterator tx_it = m_transactions.find(amount_outs_vec[i].first);
|
||||||
CHECK_AND_ASSERT_MES(tx_it != m_transactions.end(), false, "Wrong transaction id in output indexes: " <<string_tools::pod_to_hex(amount_outs_vec[i].first));
|
CHECK_AND_ASSERT_MES(tx_it != m_transactions.end(), false, "Wrong transaction id in output indexes: " << epee::string_tools::pod_to_hex(amount_outs_vec[i].first));
|
||||||
CHECK_AND_ASSERT_MES(amount_outs_vec[i].second < tx_it->second.tx.vout.size(), false,
|
CHECK_AND_ASSERT_MES(amount_outs_vec[i].second < tx_it->second.tx.vout.size(), false,
|
||||||
"Wrong index in transaction outputs: " << amount_outs_vec[i].second << ", expected less then " << tx_it->second.tx.vout.size());
|
"Wrong index in transaction outputs: " << amount_outs_vec[i].second << ", expected less then " << tx_it->second.tx.vout.size());
|
||||||
if(!vis.handle_output(tx_it->second.tx, tx_it->second.tx.vout[amount_outs_vec[i].second]))
|
if(!vis.handle_output(tx_it->second.tx, tx_it->second.tx.vout[amount_outs_vec[i].second]))
|
||||||
|
|
|
@ -29,10 +29,11 @@ namespace cryptonote
|
||||||
return !m_points.empty() && (height <= (--m_points.end())->first);
|
return !m_points.empty() && (height <= (--m_points.end())->first);
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
bool checkpoints::check_block(uint64_t height, const crypto::hash& h) const
|
bool checkpoints::check_block(uint64_t height, const crypto::hash& h, bool& is_a_checkpoint) const
|
||||||
{
|
{
|
||||||
auto it = m_points.find(height);
|
auto it = m_points.find(height);
|
||||||
if(it == m_points.end())
|
is_a_checkpoint = it != m_points.end();
|
||||||
|
if(!is_a_checkpoint)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if(it->second == h)
|
if(it->second == h)
|
||||||
|
@ -45,4 +46,25 @@ namespace cryptonote
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
bool checkpoints::check_block(uint64_t height, const crypto::hash& h) const
|
||||||
|
{
|
||||||
|
bool ignored;
|
||||||
|
return check_block(height, h, ignored);
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------
|
||||||
|
bool checkpoints::is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const
|
||||||
|
{
|
||||||
|
if (0 == block_height)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto it = m_points.upper_bound(blockchain_height);
|
||||||
|
// Is blockchain_height before the first checkpoint?
|
||||||
|
if (it == m_points.begin())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
--it;
|
||||||
|
uint64_t checkpoint_height = it->first;
|
||||||
|
return checkpoint_height < block_height;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,9 @@ namespace cryptonote
|
||||||
bool add_checkpoint(uint64_t height, const std::string& hash_str);
|
bool add_checkpoint(uint64_t height, const std::string& hash_str);
|
||||||
bool is_in_checkpoint_zone(uint64_t height) const;
|
bool is_in_checkpoint_zone(uint64_t height) const;
|
||||||
bool check_block(uint64_t height, const crypto::hash& h) const;
|
bool check_block(uint64_t height, const crypto::hash& h) const;
|
||||||
|
bool check_block(uint64_t height, const crypto::hash& h, bool& is_a_checkpoint) const;
|
||||||
|
bool is_alternative_block_allowed(uint64_t blockchain_height, uint64_t block_height) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::map<uint64_t, crypto::hash> m_points;
|
std::map<uint64_t, crypto::hash> m_points;
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,6 +13,9 @@ namespace cryptonote {
|
||||||
inline bool create_checkpoints(cryptonote::checkpoints& checkpoints)
|
inline bool create_checkpoints(cryptonote::checkpoints& checkpoints)
|
||||||
{
|
{
|
||||||
ADD_CHECKPOINT(22231, "7cb10e29d67e1c069e6e11b17d30b809724255fee2f6868dc14cfc6ed44dfb25");
|
ADD_CHECKPOINT(22231, "7cb10e29d67e1c069e6e11b17d30b809724255fee2f6868dc14cfc6ed44dfb25");
|
||||||
|
ADD_CHECKPOINT(29556, "53c484a8ed91e4da621bb2fa88106dbde426fe90d7ef07b9c1e5127fb6f3a7f6");
|
||||||
|
ADD_CHECKPOINT(50000, "0fe8758ab06a8b9cb35b7328fd4f757af530a5d37759f9d3e421023231f7b31c");
|
||||||
|
ADD_CHECKPOINT(80000, "a62dcd7b536f22e003ebae8726e9e7276f63d594e264b6f0cd7aab27b66e75e3");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,7 +28,8 @@ namespace cryptonote
|
||||||
m_blockchain_storage(m_mempool),
|
m_blockchain_storage(m_mempool),
|
||||||
m_miner(this),
|
m_miner(this),
|
||||||
m_miner_address(boost::value_initialized<account_public_address>()),
|
m_miner_address(boost::value_initialized<account_public_address>()),
|
||||||
m_starter_message_showed(false)
|
m_starter_message_showed(false),
|
||||||
|
m_target_blockchain_height(0)
|
||||||
{
|
{
|
||||||
set_cryptonote_protocol(pprotocol);
|
set_cryptonote_protocol(pprotocol);
|
||||||
}
|
}
|
||||||
|
@ -431,6 +432,18 @@ namespace cryptonote
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------
|
||||||
|
// Used by the RPC server to check the size of an incoming
|
||||||
|
// block_blob
|
||||||
|
bool core::check_incoming_block_size(const blobdata& block_blob)
|
||||||
|
{
|
||||||
|
if(block_blob.size() > get_max_block_size())
|
||||||
|
{
|
||||||
|
LOG_PRINT_L0("WRONG BLOCK BLOB, too big size " << block_blob.size() << ", rejected");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------------------------
|
||||||
crypto::hash core::get_tail_id()
|
crypto::hash core::get_tail_id()
|
||||||
{
|
{
|
||||||
return m_blockchain_storage.get_tail_id();
|
return m_blockchain_storage.get_tail_id();
|
||||||
|
@ -502,7 +515,7 @@ namespace cryptonote
|
||||||
LOG_PRINT_L0(ENDL << "**********************************************************************" << ENDL
|
LOG_PRINT_L0(ENDL << "**********************************************************************" << ENDL
|
||||||
<< "The daemon will start synchronizing with the network. It may take up to several hours." << ENDL
|
<< "The daemon will start synchronizing with the network. It may take up to several hours." << ENDL
|
||||||
<< ENDL
|
<< ENDL
|
||||||
<< "You can set the level of process detailization by using command \"set_log <level>\", where <level> is either 0 (no details), 1 (current block height synchronized), or 2 (all details)." << ENDL
|
<< "You can set the level of process detailization* through \"set_log <level>\" command*, where <level> is between 0 (no details) and 4 (very verbose)." << ENDL
|
||||||
<< ENDL
|
<< ENDL
|
||||||
<< "Use \"help\" command to see the list of available commands." << ENDL
|
<< "Use \"help\" command to see the list of available commands." << ENDL
|
||||||
<< ENDL
|
<< ENDL
|
||||||
|
@ -513,7 +526,15 @@ namespace cryptonote
|
||||||
|
|
||||||
m_store_blockchain_interval.do_call(boost::bind(&blockchain_storage::store_blockchain, &m_blockchain_storage));
|
m_store_blockchain_interval.do_call(boost::bind(&blockchain_storage::store_blockchain, &m_blockchain_storage));
|
||||||
m_miner.on_idle();
|
m_miner.on_idle();
|
||||||
|
m_mempool.on_idle();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------
|
||||||
|
void core::set_target_blockchain_height(uint64_t target_blockchain_height) {
|
||||||
|
m_target_blockchain_height = target_blockchain_height;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------------------------
|
||||||
|
uint64_t core::get_target_blockchain_height() const {
|
||||||
|
return m_target_blockchain_height;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,6 +34,7 @@ namespace cryptonote
|
||||||
bool on_idle();
|
bool on_idle();
|
||||||
bool handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool keeped_by_block);
|
bool handle_incoming_tx(const blobdata& tx_blob, tx_verification_context& tvc, bool keeped_by_block);
|
||||||
bool handle_incoming_block(const blobdata& block_blob, block_verification_context& bvc, bool update_miner_blocktemplate = true);
|
bool handle_incoming_block(const blobdata& block_blob, block_verification_context& bvc, bool update_miner_blocktemplate = true);
|
||||||
|
bool check_incoming_block_size(const blobdata& block_blob);
|
||||||
i_cryptonote_protocol* get_protocol(){return m_pprotocol;}
|
i_cryptonote_protocol* get_protocol(){return m_pprotocol;}
|
||||||
|
|
||||||
//-------------------- i_miner_handler -----------------------
|
//-------------------- i_miner_handler -----------------------
|
||||||
|
@ -90,6 +91,9 @@ namespace cryptonote
|
||||||
void print_blockchain_outs(const std::string& file);
|
void print_blockchain_outs(const std::string& file);
|
||||||
void on_synchronized();
|
void on_synchronized();
|
||||||
|
|
||||||
|
void set_target_blockchain_height(uint64_t target_blockchain_height);
|
||||||
|
uint64_t get_target_blockchain_height() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool add_new_tx(const transaction& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prefix_hash, size_t blob_size, tx_verification_context& tvc, bool keeped_by_block);
|
bool add_new_tx(const transaction& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prefix_hash, size_t blob_size, tx_verification_context& tvc, bool keeped_by_block);
|
||||||
bool add_new_tx(const transaction& tx, tx_verification_context& tvc, bool keeped_by_block);
|
bool add_new_tx(const transaction& tx, tx_verification_context& tvc, bool keeped_by_block);
|
||||||
|
@ -115,15 +119,17 @@ namespace cryptonote
|
||||||
tx_memory_pool m_mempool;
|
tx_memory_pool m_mempool;
|
||||||
blockchain_storage m_blockchain_storage;
|
blockchain_storage m_blockchain_storage;
|
||||||
i_cryptonote_protocol* m_pprotocol;
|
i_cryptonote_protocol* m_pprotocol;
|
||||||
critical_section m_incoming_tx_lock;
|
epee::critical_section m_incoming_tx_lock;
|
||||||
//m_miner and m_miner_addres are probably temporary here
|
//m_miner and m_miner_addres are probably temporary here
|
||||||
miner m_miner;
|
miner m_miner;
|
||||||
account_public_address m_miner_address;
|
account_public_address m_miner_address;
|
||||||
std::string m_config_folder;
|
std::string m_config_folder;
|
||||||
cryptonote_protocol_stub m_protocol_stub;
|
cryptonote_protocol_stub m_protocol_stub;
|
||||||
math_helper::once_a_time_seconds<60*60*12, false> m_store_blockchain_interval;
|
epee::math_helper::once_a_time_seconds<60*60*12, false> m_store_blockchain_interval;
|
||||||
friend class tx_validate_inputs;
|
friend class tx_validate_inputs;
|
||||||
std::atomic<bool> m_starter_message_showed;
|
std::atomic<bool> m_starter_message_showed;
|
||||||
|
|
||||||
|
uint64_t m_target_blockchain_height;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -80,7 +80,7 @@ namespace cryptonote
|
||||||
#endif
|
#endif
|
||||||
block_reward += fee;
|
block_reward += fee;
|
||||||
|
|
||||||
std::vector<size_t> out_amounts;
|
std::vector<uint64_t> out_amounts;
|
||||||
decompose_amount_into_digits(block_reward, DEFAULT_FEE,
|
decompose_amount_into_digits(block_reward, DEFAULT_FEE,
|
||||||
[&out_amounts](uint64_t a_chunk) { out_amounts.push_back(a_chunk); },
|
[&out_amounts](uint64_t a_chunk) { out_amounts.push_back(a_chunk); },
|
||||||
[&out_amounts](uint64_t a_dust) { out_amounts.push_back(a_dust); });
|
[&out_amounts](uint64_t a_dust) { out_amounts.push_back(a_dust); });
|
||||||
|
@ -92,7 +92,7 @@ namespace cryptonote
|
||||||
out_amounts.resize(out_amounts.size() - 1);
|
out_amounts.resize(out_amounts.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t summary_amounts = 0;
|
uint64_t summary_amounts = 0;
|
||||||
for (size_t no = 0; no < out_amounts.size(); no++)
|
for (size_t no = 0; no < out_amounts.size(); no++)
|
||||||
{
|
{
|
||||||
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);;
|
crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);;
|
||||||
|
@ -239,8 +239,7 @@ namespace cryptonote
|
||||||
crypto::public_key get_tx_pub_key_from_extra(const std::vector<uint8_t>& tx_extra)
|
crypto::public_key get_tx_pub_key_from_extra(const std::vector<uint8_t>& tx_extra)
|
||||||
{
|
{
|
||||||
std::vector<tx_extra_field> tx_extra_fields;
|
std::vector<tx_extra_field> tx_extra_fields;
|
||||||
if (!parse_tx_extra(tx_extra, tx_extra_fields))
|
parse_tx_extra(tx_extra, tx_extra_fields);
|
||||||
return null_pkey;
|
|
||||||
|
|
||||||
tx_extra_pub_key pub_key_field;
|
tx_extra_pub_key pub_key_field;
|
||||||
if(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field))
|
if(!find_tx_extra_field_by_type(tx_extra_fields, pub_key_field))
|
||||||
|
|
|
@ -188,11 +188,20 @@ namespace cryptonote
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
||||||
bool miner::is_mining()
|
bool miner::is_mining() const
|
||||||
{
|
{
|
||||||
return !m_stop;
|
return !m_stop;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
||||||
|
const account_public_address& miner::get_mining_address() const
|
||||||
|
{
|
||||||
|
return m_mine_address;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------------------------------
|
||||||
|
uint32_t miner::get_threads_count() const {
|
||||||
|
return m_threads_total;
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------------------------------
|
||||||
bool miner::start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs)
|
bool miner::start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs)
|
||||||
{
|
{
|
||||||
m_mine_address = adr;
|
m_mine_address = adr;
|
||||||
|
@ -226,12 +235,14 @@ namespace cryptonote
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
||||||
uint64_t miner::get_speed()
|
uint64_t miner::get_speed() const
|
||||||
{
|
{
|
||||||
if(is_mining())
|
if(is_mining()) {
|
||||||
return m_current_hash_rate;
|
return m_current_hash_rate;
|
||||||
else
|
}
|
||||||
|
else {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
||||||
void miner::send_stop_signal()
|
void miner::send_stop_signal()
|
||||||
|
|
|
@ -4,7 +4,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <boost/atomic.hpp>
|
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include "cryptonote_basic.h"
|
#include "cryptonote_basic.h"
|
||||||
|
@ -36,10 +35,12 @@ namespace cryptonote
|
||||||
bool set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height);
|
bool set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height);
|
||||||
bool on_block_chain_update();
|
bool on_block_chain_update();
|
||||||
bool start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs);
|
bool start(const account_public_address& adr, size_t threads_count, const boost::thread::attributes& attrs);
|
||||||
uint64_t get_speed();
|
uint64_t get_speed() const;
|
||||||
|
uint32_t get_threads_count() const;
|
||||||
void send_stop_signal();
|
void send_stop_signal();
|
||||||
bool stop();
|
bool stop();
|
||||||
bool is_mining();
|
bool is_mining() const;
|
||||||
|
const account_public_address& get_mining_address() const;
|
||||||
bool on_idle();
|
bool on_idle();
|
||||||
void on_synchronized();
|
void on_synchronized();
|
||||||
//synchronous analog (for fast calls)
|
//synchronous analog (for fast calls)
|
||||||
|
@ -64,7 +65,7 @@ namespace cryptonote
|
||||||
|
|
||||||
|
|
||||||
volatile uint32_t m_stop;
|
volatile uint32_t m_stop;
|
||||||
::critical_section m_template_lock;
|
epee::critical_section m_template_lock;
|
||||||
block m_template;
|
block m_template;
|
||||||
std::atomic<uint32_t> m_template_no;
|
std::atomic<uint32_t> m_template_no;
|
||||||
std::atomic<uint32_t> m_starter_nonce;
|
std::atomic<uint32_t> m_starter_nonce;
|
||||||
|
@ -73,21 +74,21 @@ namespace cryptonote
|
||||||
volatile uint32_t m_thread_index;
|
volatile uint32_t m_thread_index;
|
||||||
volatile uint32_t m_threads_total;
|
volatile uint32_t m_threads_total;
|
||||||
std::atomic<int32_t> m_pausers_count;
|
std::atomic<int32_t> m_pausers_count;
|
||||||
::critical_section m_miners_count_lock;
|
epee::critical_section m_miners_count_lock;
|
||||||
|
|
||||||
std::list<boost::thread> m_threads;
|
std::list<boost::thread> m_threads;
|
||||||
::critical_section m_threads_lock;
|
epee::critical_section m_threads_lock;
|
||||||
i_miner_handler* m_phandler;
|
i_miner_handler* m_phandler;
|
||||||
account_public_address m_mine_address;
|
account_public_address m_mine_address;
|
||||||
math_helper::once_a_time_seconds<5> m_update_block_template_interval;
|
epee::math_helper::once_a_time_seconds<5> m_update_block_template_interval;
|
||||||
math_helper::once_a_time_seconds<2> m_update_merge_hr_interval;
|
epee::math_helper::once_a_time_seconds<2> m_update_merge_hr_interval;
|
||||||
std::vector<blobdata> m_extra_messages;
|
std::vector<blobdata> m_extra_messages;
|
||||||
miner_config m_config;
|
miner_config m_config;
|
||||||
std::string m_config_folder_path;
|
std::string m_config_folder_path;
|
||||||
std::atomic<uint64_t> m_last_hr_merge_time;
|
std::atomic<uint64_t> m_last_hr_merge_time;
|
||||||
std::atomic<uint64_t> m_hashes;
|
std::atomic<uint64_t> m_hashes;
|
||||||
std::atomic<uint64_t> m_current_hash_rate;
|
std::atomic<uint64_t> m_current_hash_rate;
|
||||||
critical_section m_last_hash_rates_lock;
|
epee::critical_section m_last_hash_rates_lock;
|
||||||
std::list<uint64_t> m_last_hash_rates;
|
std::list<uint64_t> m_last_hash_rates;
|
||||||
bool m_do_print_hashrate;
|
bool m_do_print_hashrate;
|
||||||
bool m_do_mining;
|
bool m_do_mining;
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#define TX_EXTRA_TAG_PADDING 0x00
|
#define TX_EXTRA_TAG_PADDING 0x00
|
||||||
#define TX_EXTRA_TAG_PUBKEY 0x01
|
#define TX_EXTRA_TAG_PUBKEY 0x01
|
||||||
#define TX_EXTRA_NONCE 0x02
|
#define TX_EXTRA_NONCE 0x02
|
||||||
|
#define TX_EXTRA_MERGE_MINING_TAG 0x03
|
||||||
|
|
||||||
#define TX_EXTRA_NONCE_PAYMENT_ID 0x00
|
#define TX_EXTRA_NONCE_PAYMENT_ID 0x00
|
||||||
|
|
||||||
|
@ -82,13 +83,62 @@ namespace cryptonote
|
||||||
END_SERIALIZE()
|
END_SERIALIZE()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct tx_extra_merge_mining_tag
|
||||||
|
{
|
||||||
|
struct serialize_helper
|
||||||
|
{
|
||||||
|
tx_extra_merge_mining_tag& mm_tag;
|
||||||
|
|
||||||
|
serialize_helper(tx_extra_merge_mining_tag& mm_tag_) : mm_tag(mm_tag_)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
BEGIN_SERIALIZE()
|
||||||
|
VARINT_FIELD_N("depth", mm_tag.depth)
|
||||||
|
FIELD_N("merkle_root", mm_tag.merkle_root)
|
||||||
|
END_SERIALIZE()
|
||||||
|
};
|
||||||
|
|
||||||
|
size_t depth;
|
||||||
|
crypto::hash merkle_root;
|
||||||
|
|
||||||
|
// load
|
||||||
|
template <template <bool> class Archive>
|
||||||
|
bool do_serialize(Archive<false>& ar)
|
||||||
|
{
|
||||||
|
std::string field;
|
||||||
|
if(!::do_serialize(ar, field))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::istringstream iss(field);
|
||||||
|
binary_archive<false> iar(iss);
|
||||||
|
serialize_helper helper(*this);
|
||||||
|
return ::serialization::serialize(iar, helper);
|
||||||
|
}
|
||||||
|
|
||||||
|
// store
|
||||||
|
template <template <bool> class Archive>
|
||||||
|
bool do_serialize(Archive<true>& ar)
|
||||||
|
{
|
||||||
|
std::ostringstream oss;
|
||||||
|
binary_archive<true> oar(oss);
|
||||||
|
serialize_helper helper(*this);
|
||||||
|
if(!::do_serialize(oar, helper))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
std::string field = oss.str();
|
||||||
|
return ::serialization::serialize(ar, field);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// tx_extra_field format, except tx_extra_padding and tx_extra_pub_key:
|
// tx_extra_field format, except tx_extra_padding and tx_extra_pub_key:
|
||||||
// varint tag;
|
// varint tag;
|
||||||
// varint size;
|
// varint size;
|
||||||
// varint data[];
|
// varint data[];
|
||||||
typedef boost::variant<tx_extra_padding, tx_extra_pub_key, tx_extra_nonce> tx_extra_field;
|
typedef boost::variant<tx_extra_padding, tx_extra_pub_key, tx_extra_nonce, tx_extra_merge_mining_tag> tx_extra_field;
|
||||||
}
|
}
|
||||||
|
|
||||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_padding, TX_EXTRA_TAG_PADDING);
|
VARIANT_TAG(binary_archive, cryptonote::tx_extra_padding, TX_EXTRA_TAG_PADDING);
|
||||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_pub_key, TX_EXTRA_TAG_PUBKEY);
|
VARIANT_TAG(binary_archive, cryptonote::tx_extra_pub_key, TX_EXTRA_TAG_PUBKEY);
|
||||||
VARIANT_TAG(binary_archive, cryptonote::tx_extra_nonce, TX_EXTRA_NONCE);
|
VARIANT_TAG(binary_archive, cryptonote::tx_extra_nonce, TX_EXTRA_NONCE);
|
||||||
|
VARIANT_TAG(binary_archive, cryptonote::tx_extra_merge_mining_tag, TX_EXTRA_MERGE_MINING_TAG);
|
||||||
|
|
|
@ -83,6 +83,7 @@ namespace cryptonote
|
||||||
txd_p.first->second.max_used_block_id = null_hash;
|
txd_p.first->second.max_used_block_id = null_hash;
|
||||||
txd_p.first->second.max_used_block_height = 0;
|
txd_p.first->second.max_used_block_height = 0;
|
||||||
txd_p.first->second.kept_by_block = kept_by_block;
|
txd_p.first->second.kept_by_block = kept_by_block;
|
||||||
|
txd_p.first->second.receive_time = time(nullptr);
|
||||||
tvc.m_verifivation_impossible = true;
|
tvc.m_verifivation_impossible = true;
|
||||||
tvc.m_added_to_pool = true;
|
tvc.m_added_to_pool = true;
|
||||||
}else
|
}else
|
||||||
|
@ -104,6 +105,7 @@ namespace cryptonote
|
||||||
txd_p.first->second.max_used_block_height = max_used_block_height;
|
txd_p.first->second.max_used_block_height = max_used_block_height;
|
||||||
txd_p.first->second.last_failed_height = 0;
|
txd_p.first->second.last_failed_height = 0;
|
||||||
txd_p.first->second.last_failed_id = null_hash;
|
txd_p.first->second.last_failed_id = null_hash;
|
||||||
|
txd_p.first->second.receive_time = time(nullptr);
|
||||||
tvc.m_added_to_pool = true;
|
tvc.m_added_to_pool = true;
|
||||||
|
|
||||||
if(txd_p.first->second.fee > 0)
|
if(txd_p.first->second.fee > 0)
|
||||||
|
@ -178,6 +180,30 @@ namespace cryptonote
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
|
void tx_memory_pool::on_idle()
|
||||||
|
{
|
||||||
|
m_remove_stuck_tx_interval.do_call([this](){return remove_stuck_transactions();});
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
//proper tx_pool handling courtesy of CryptoZoidberg and Boolberry
|
||||||
|
bool tx_memory_pool::remove_stuck_transactions()
|
||||||
|
{
|
||||||
|
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||||
|
for(auto it = m_transactions.begin(); it!= m_transactions.end();)
|
||||||
|
{
|
||||||
|
uint64_t tx_age = time(nullptr) - it->second.receive_time;
|
||||||
|
|
||||||
|
if((tx_age > CRYPTONOTE_MEMPOOL_TX_LIVETIME && !it->second.kept_by_block) ||
|
||||||
|
(tx_age > CRYPTONOTE_MEMPOOL_TX_FROM_ALT_BLOCK_LIVETIME && it->second.kept_by_block) )
|
||||||
|
{
|
||||||
|
LOG_PRINT_L0("Tx " << it->first << " removed from tx pool due to outdated, age: " << tx_age );
|
||||||
|
m_transactions.erase(it++);
|
||||||
|
}else
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
size_t tx_memory_pool::get_transactions_count()
|
size_t tx_memory_pool::get_transactions_count()
|
||||||
{
|
{
|
||||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||||
|
@ -350,18 +376,69 @@ namespace cryptonote
|
||||||
//---------------------------------------------------------------------------------
|
//---------------------------------------------------------------------------------
|
||||||
bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t already_generated_coins, size_t &total_size, uint64_t &fee)
|
bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t already_generated_coins, size_t &total_size, uint64_t &fee)
|
||||||
{
|
{
|
||||||
|
// Warning: This function takes already_generated_
|
||||||
|
// coins as an argument and appears to do nothing
|
||||||
|
// with it.
|
||||||
|
|
||||||
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
CRITICAL_REGION_LOCAL(m_transactions_lock);
|
||||||
|
|
||||||
total_size = 0;
|
total_size = 0;
|
||||||
fee = 0;
|
fee = 0;
|
||||||
|
|
||||||
size_t max_total_size = 2 * median_size - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
|
size_t max_total_size = 2 * median_size - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE; // Max block size
|
||||||
std::unordered_set<crypto::key_image> k_images;
|
std::unordered_set<crypto::key_image> k_images;
|
||||||
|
|
||||||
|
// Tx size limit as in wallet2.h
|
||||||
|
// tx_pool.cpp uses size_t for tx sizes, whereas
|
||||||
|
// wallet2.h uses uint64_t; just use size_t here
|
||||||
|
// for now
|
||||||
|
size_t upper_transaction_size_limit = ((CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
|
||||||
|
|
||||||
|
// Calculate size limit based on median too; useful
|
||||||
|
// for when we actually fix wallet2.h's maximum
|
||||||
|
// allowable tx size
|
||||||
|
//
|
||||||
|
// Can be removed when wallet2.h calculates max
|
||||||
|
// tx size based on the median too; just use
|
||||||
|
// upper_transaction_size_limit_median in all cases
|
||||||
|
size_t upper_transaction_size_limit_median = ((median_size * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
|
||||||
|
if (upper_transaction_size_limit_median > upper_transaction_size_limit)
|
||||||
|
upper_transaction_size_limit = upper_transaction_size_limit_median;
|
||||||
|
|
||||||
BOOST_FOREACH(transactions_container::value_type& tx, m_transactions)
|
BOOST_FOREACH(transactions_container::value_type& tx, m_transactions)
|
||||||
{
|
{
|
||||||
|
// Can not exceed maximum block size
|
||||||
if (max_total_size < total_size + tx.second.blob_size)
|
if (max_total_size < total_size + tx.second.blob_size)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
// Check to see if the minimum fee is included;
|
||||||
|
// exclude tx missing minimum fee
|
||||||
|
if (tx.second.fee < DEFAULT_FEE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Skip transactions that are too large
|
||||||
|
// TODO: Correct upper_transactions_size_limit
|
||||||
|
// such that it is based on median block size;
|
||||||
|
// We need to make a similar patch for
|
||||||
|
// wallet2.h
|
||||||
|
if (tx.second.blob_size > upper_transaction_size_limit)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// If adding this tx will make the block size
|
||||||
|
// greater than 130% of the median, reject the
|
||||||
|
// tx; this will keep down largely punitive tx
|
||||||
|
// from being included
|
||||||
|
if ( (total_size + tx.second.blob_size) > ((130 * median_size) / 100) )
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// If we've exceeded the penalty free size,
|
||||||
|
// stop including more tx
|
||||||
|
if (total_size > median_size)
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Skip transactions that are not ready to be
|
||||||
|
// included into the blockchain or that are
|
||||||
|
// missing key images
|
||||||
if (!is_transaction_ready_to_go(tx.second) || have_key_images(k_images, tx.second.tx))
|
if (!is_transaction_ready_to_go(tx.second) || have_key_images(k_images, tx.second.tx))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -4,8 +4,6 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "include_base_utils.h"
|
#include "include_base_utils.h"
|
||||||
using namespace epee;
|
|
||||||
|
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
@ -15,6 +13,7 @@ using namespace epee;
|
||||||
|
|
||||||
#include "string_tools.h"
|
#include "string_tools.h"
|
||||||
#include "syncobj.h"
|
#include "syncobj.h"
|
||||||
|
#include "math_helper.h"
|
||||||
#include "cryptonote_basic_impl.h"
|
#include "cryptonote_basic_impl.h"
|
||||||
#include "verification_context.h"
|
#include "verification_context.h"
|
||||||
#include "crypto/hash.h"
|
#include "crypto/hash.h"
|
||||||
|
@ -42,6 +41,7 @@ namespace cryptonote
|
||||||
|
|
||||||
bool on_blockchain_inc(uint64_t new_block_height, const crypto::hash& top_block_id);
|
bool on_blockchain_inc(uint64_t new_block_height, const crypto::hash& top_block_id);
|
||||||
bool on_blockchain_dec(uint64_t new_block_height, const crypto::hash& top_block_id);
|
bool on_blockchain_dec(uint64_t new_block_height, const crypto::hash& top_block_id);
|
||||||
|
void on_idle();
|
||||||
|
|
||||||
void lock();
|
void lock();
|
||||||
void unlock();
|
void unlock();
|
||||||
|
@ -61,7 +61,7 @@ namespace cryptonote
|
||||||
/*bool flush_pool(const std::strig& folder);
|
/*bool flush_pool(const std::strig& folder);
|
||||||
bool inflate_pool(const std::strig& folder);*/
|
bool inflate_pool(const std::strig& folder);*/
|
||||||
|
|
||||||
#define CURRENT_MEMPOOL_ARCHIVE_VER 7
|
#define CURRENT_MEMPOOL_ARCHIVE_VER 8
|
||||||
|
|
||||||
template<class archive_t>
|
template<class archive_t>
|
||||||
void serialize(archive_t & a, const unsigned int version)
|
void serialize(archive_t & a, const unsigned int version)
|
||||||
|
@ -84,9 +84,11 @@ namespace cryptonote
|
||||||
//
|
//
|
||||||
uint64_t last_failed_height;
|
uint64_t last_failed_height;
|
||||||
crypto::hash last_failed_id;
|
crypto::hash last_failed_id;
|
||||||
|
time_t receive_time;
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool remove_stuck_transactions();
|
||||||
bool is_transaction_ready_to_go(tx_details& txd);
|
bool is_transaction_ready_to_go(tx_details& txd);
|
||||||
typedef std::unordered_map<crypto::hash, tx_details > transactions_container;
|
typedef std::unordered_map<crypto::hash, tx_details > transactions_container;
|
||||||
typedef std::unordered_map<crypto::key_image, std::unordered_set<crypto::hash> > key_images_container;
|
typedef std::unordered_map<crypto::key_image, std::unordered_set<crypto::hash> > key_images_container;
|
||||||
|
@ -94,6 +96,7 @@ namespace cryptonote
|
||||||
epee::critical_section m_transactions_lock;
|
epee::critical_section m_transactions_lock;
|
||||||
transactions_container m_transactions;
|
transactions_container m_transactions;
|
||||||
key_images_container m_spent_key_images;
|
key_images_container m_spent_key_images;
|
||||||
|
epee::math_helper::once_a_time_seconds<30> m_remove_stuck_tx_interval;
|
||||||
|
|
||||||
//transactions_container m_alternative_transactions;
|
//transactions_container m_alternative_transactions;
|
||||||
|
|
||||||
|
@ -161,6 +164,7 @@ namespace boost
|
||||||
ar & td.max_used_block_id;
|
ar & td.max_used_block_id;
|
||||||
ar & td.last_failed_height;
|
ar & td.last_failed_height;
|
||||||
ar & td.last_failed_id;
|
ar & td.last_failed_id;
|
||||||
|
ar & td.receive_time;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace cryptonote
|
||||||
template<class t_parametr>
|
template<class t_parametr>
|
||||||
bool post_notify(typename t_parametr::request& arg, cryptonote_connection_context& context)
|
bool post_notify(typename t_parametr::request& arg, cryptonote_connection_context& context)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L2("[" << net_utils::print_connection_context_short(context) << "] post " << typeid(t_parametr).name() << " -->");
|
LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(context) << "] post " << typeid(t_parametr).name() << " -->");
|
||||||
std::string blob;
|
std::string blob;
|
||||||
epee::serialization::store_t_to_binary(arg, blob);
|
epee::serialization::store_t_to_binary(arg, blob);
|
||||||
return m_p2p->invoke_notify_to_peer(t_parametr::ID, blob, context);
|
return m_p2p->invoke_notify_to_peer(t_parametr::ID, blob, context);
|
||||||
|
@ -90,7 +90,7 @@ namespace cryptonote
|
||||||
template<class t_parametr>
|
template<class t_parametr>
|
||||||
bool relay_post_notify(typename t_parametr::request& arg, cryptonote_connection_context& exlude_context)
|
bool relay_post_notify(typename t_parametr::request& arg, cryptonote_connection_context& exlude_context)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L2("[" << net_utils::print_connection_context_short(exlude_context) << "] post relay " << typeid(t_parametr).name() << " -->");
|
LOG_PRINT_L2("[" << epee::net_utils::print_connection_context_short(exlude_context) << "] post relay " << typeid(t_parametr).name() << " -->");
|
||||||
std::string arg_buff;
|
std::string arg_buff;
|
||||||
epee::serialization::store_t_to_binary(arg, arg_buff);
|
epee::serialization::store_t_to_binary(arg, arg_buff);
|
||||||
return m_p2p->relay_notify_to_all(t_parametr::ID, arg_buff, exlude_context);
|
return m_p2p->relay_notify_to_all(t_parametr::ID, arg_buff, exlude_context);
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace cryptonote
|
||||||
m_p2p->for_each_connection([&](const connection_context& cntxt, nodetool::peerid_type peer_id)
|
m_p2p->for_each_connection([&](const connection_context& cntxt, nodetool::peerid_type peer_id)
|
||||||
{
|
{
|
||||||
ss << std::setw(25) << std::left << std::string(cntxt.m_is_income ? " [INC]":"[OUT]") +
|
ss << std::setw(25) << std::left << std::string(cntxt.m_is_income ? " [INC]":"[OUT]") +
|
||||||
string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) + ":" + std::to_string(cntxt.m_remote_port)
|
epee::string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) + ":" + std::to_string(cntxt.m_remote_port)
|
||||||
<< std::setw(20) << std::hex << peer_id
|
<< std::setw(20) << std::hex << peer_id
|
||||||
<< std::setw(25) << std::to_string(cntxt.m_recv_cnt)+ "(" + std::to_string(time(NULL) - cntxt.m_last_recv) + ")" + "/" + std::to_string(cntxt.m_send_cnt) + "(" + std::to_string(time(NULL) - cntxt.m_last_send) + ")"
|
<< std::setw(25) << std::to_string(cntxt.m_recv_cnt)+ "(" + std::to_string(time(NULL) - cntxt.m_last_recv) + ")" + "/" + std::to_string(cntxt.m_send_cnt) + "(" + std::to_string(time(NULL) - cntxt.m_last_send) + ")"
|
||||||
<< std::setw(25) << get_protocol_state_string(cntxt.m_state)
|
<< std::setw(25) << get_protocol_state_string(cntxt.m_state)
|
||||||
|
@ -108,9 +108,17 @@ namespace cryptonote
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_PRINT_CCONTEXT_YELLOW("Sync data returned unknown top block: " << m_core.get_current_blockchain_height() << "->" << hshd.current_height
|
/* As I don't know if accessing hshd from core could be a good practice,
|
||||||
<< "[" << static_cast<int64_t>(hshd.current_height - m_core.get_current_blockchain_height()) << " blocks(" << (hshd.current_height - m_core.get_current_blockchain_height()) /1440 << " days) behind] " << ENDL
|
I prefer pushing target height to the core at the same time it is pushed to the user.
|
||||||
<< "remote top: " << hshd.top_id << "[" << hshd.current_height << "]" << ", set SYNCHRONIZATION mode", (is_inital ? LOG_LEVEL_0:LOG_LEVEL_1));
|
Nz. */
|
||||||
|
m_core.set_target_blockchain_height(static_cast<int64_t>(hshd.current_height));
|
||||||
|
|
||||||
|
int64_t diff = static_cast<int64_t>(hshd.current_height) - static_cast<int64_t>(m_core.get_current_blockchain_height());
|
||||||
|
LOG_PRINT_CCONTEXT_YELLOW("Sync data returned unknown top block: " << m_core.get_current_blockchain_height() << " -> " << hshd.current_height
|
||||||
|
<< " [" << std::abs(diff) << " blocks (" << diff / (24 * 60 * 60 / DIFFICULTY_TARGET) << " days) "
|
||||||
|
<< (0 <= diff ? std::string("behind") : std::string("ahead"))
|
||||||
|
<< "] " << ENDL << "SYNCHRONIZATION started", (is_inital ? LOG_LEVEL_0:LOG_LEVEL_1));
|
||||||
|
LOG_PRINT_L1("Remote top block height: " << hshd.current_height << ", id: " << hshd.top_id);
|
||||||
context.m_state = cryptonote_connection_context::state_synchronizing;
|
context.m_state = cryptonote_connection_context::state_synchronizing;
|
||||||
context.m_remote_blockchain_height = hshd.current_height;
|
context.m_remote_blockchain_height = hshd.current_height;
|
||||||
//let the socket to send response to handshake, but request callback, to let send request data after response
|
//let the socket to send response to handshake, but request callback, to let send request data after response
|
||||||
|
@ -254,7 +262,7 @@ namespace cryptonote
|
||||||
if(!parse_and_validate_block_from_blob(block_entry.block, b))
|
if(!parse_and_validate_block_from_blob(block_entry.block, b))
|
||||||
{
|
{
|
||||||
LOG_ERROR_CCONTEXT("sent wrong block: failed to parse and validate block: \r\n"
|
LOG_ERROR_CCONTEXT("sent wrong block: failed to parse and validate block: \r\n"
|
||||||
<< string_tools::buff_to_hex_nodelimer(block_entry.block) << "\r\n dropping connection");
|
<< epee::string_tools::buff_to_hex_nodelimer(block_entry.block) << "\r\n dropping connection");
|
||||||
m_p2p->drop_connection(context);
|
m_p2p->drop_connection(context);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -274,14 +282,14 @@ namespace cryptonote
|
||||||
auto req_it = context.m_requested_objects.find(get_block_hash(b));
|
auto req_it = context.m_requested_objects.find(get_block_hash(b));
|
||||||
if(req_it == context.m_requested_objects.end())
|
if(req_it == context.m_requested_objects.end())
|
||||||
{
|
{
|
||||||
LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << string_tools::pod_to_hex(get_blob_hash(block_entry.block))
|
LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block))
|
||||||
<< " wasn't requested, dropping connection");
|
<< " wasn't requested, dropping connection");
|
||||||
m_p2p->drop_connection(context);
|
m_p2p->drop_connection(context);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if(b.tx_hashes.size() != block_entry.txs.size())
|
if(b.tx_hashes.size() != block_entry.txs.size())
|
||||||
{
|
{
|
||||||
LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << string_tools::pod_to_hex(get_blob_hash(block_entry.block))
|
LOG_ERROR_CCONTEXT("sent wrong NOTIFY_RESPONSE_GET_OBJECTS: block with id=" << epee::string_tools::pod_to_hex(get_blob_hash(block_entry.block))
|
||||||
<< ", tx_hashes.size()=" << b.tx_hashes.size() << " mismatch with block_complete_entry.m_txs.size()=" << block_entry.txs.size() << ", dropping connection");
|
<< ", tx_hashes.size()=" << b.tx_hashes.size() << " mismatch with block_complete_entry.m_txs.size()=" << block_entry.txs.size() << ", dropping connection");
|
||||||
m_p2p->drop_connection(context);
|
m_p2p->drop_connection(context);
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -300,7 +308,7 @@ namespace cryptonote
|
||||||
|
|
||||||
{
|
{
|
||||||
m_core.pause_mine();
|
m_core.pause_mine();
|
||||||
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler(
|
epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler(
|
||||||
boost::bind(&t_core::resume_mine, &m_core));
|
boost::bind(&t_core::resume_mine, &m_core));
|
||||||
|
|
||||||
BOOST_FOREACH(const block_complete_entry& block_entry, arg.blocks)
|
BOOST_FOREACH(const block_complete_entry& block_entry, arg.blocks)
|
||||||
|
@ -314,7 +322,7 @@ namespace cryptonote
|
||||||
if(tvc.m_verifivation_failed)
|
if(tvc.m_verifivation_failed)
|
||||||
{
|
{
|
||||||
LOG_ERROR_CCONTEXT("transaction verification failed on NOTIFY_RESPONSE_GET_OBJECTS, \r\ntx_id = "
|
LOG_ERROR_CCONTEXT("transaction verification failed on NOTIFY_RESPONSE_GET_OBJECTS, \r\ntx_id = "
|
||||||
<< string_tools::pod_to_hex(get_blob_hash(tx_blob)) << ", dropping connection");
|
<< epee::string_tools::pod_to_hex(get_blob_hash(tx_blob)) << ", dropping connection");
|
||||||
m_p2p->drop_connection(context);
|
m_p2p->drop_connection(context);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -408,7 +416,7 @@ namespace cryptonote
|
||||||
<< "\r\nm_remote_blockchain_height=" << context.m_remote_blockchain_height
|
<< "\r\nm_remote_blockchain_height=" << context.m_remote_blockchain_height
|
||||||
<< "\r\nm_needed_objects.size()=" << context.m_needed_objects.size()
|
<< "\r\nm_needed_objects.size()=" << context.m_needed_objects.size()
|
||||||
<< "\r\nm_requested_objects.size()=" << context.m_requested_objects.size()
|
<< "\r\nm_requested_objects.size()=" << context.m_requested_objects.size()
|
||||||
<< "\r\non connection [" << net_utils::print_connection_context_short(context)<< "]");
|
<< "\r\non connection [" << epee::net_utils::print_connection_context_short(context)<< "]");
|
||||||
|
|
||||||
context.m_state = cryptonote_connection_context::state_normal;
|
context.m_state = cryptonote_connection_context::state_normal;
|
||||||
LOG_PRINT_CCONTEXT_GREEN(" SYNCHRONIZED OK", LOG_LEVEL_0);
|
LOG_PRINT_CCONTEXT_GREEN(" SYNCHRONIZED OK", LOG_LEVEL_0);
|
||||||
|
@ -464,7 +472,7 @@ namespace cryptonote
|
||||||
if(!m_core.have_block(arg.m_block_ids.front()))
|
if(!m_core.have_block(arg.m_block_ids.front()))
|
||||||
{
|
{
|
||||||
LOG_ERROR_CCONTEXT("sent m_block_ids starting from unknown id: "
|
LOG_ERROR_CCONTEXT("sent m_block_ids starting from unknown id: "
|
||||||
<< string_tools::pod_to_hex(arg.m_block_ids.front()) << " , dropping connection");
|
<< epee::string_tools::pod_to_hex(arg.m_block_ids.front()) << " , dropping connection");
|
||||||
m_p2p->drop_connection(context);
|
m_p2p->drop_connection(context);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
|
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
#include "crypto/hash.h"
|
#include "crypto/hash.h"
|
||||||
|
#include "version.h"
|
||||||
|
|
||||||
|
|
||||||
class daemon_cmmands_handler
|
class daemon_cmmands_handler
|
||||||
|
@ -34,6 +35,8 @@ public:
|
||||||
m_cmd_binder.set_handler("show_hr", boost::bind(&daemon_cmmands_handler::show_hr, this, _1), "Start showing hash rate");
|
m_cmd_binder.set_handler("show_hr", boost::bind(&daemon_cmmands_handler::show_hr, this, _1), "Start showing hash rate");
|
||||||
m_cmd_binder.set_handler("hide_hr", boost::bind(&daemon_cmmands_handler::hide_hr, this, _1), "Stop showing hash rate");
|
m_cmd_binder.set_handler("hide_hr", boost::bind(&daemon_cmmands_handler::hide_hr, this, _1), "Stop showing hash rate");
|
||||||
m_cmd_binder.set_handler("save", boost::bind(&daemon_cmmands_handler::save, this, _1), "Save blockchain");
|
m_cmd_binder.set_handler("save", boost::bind(&daemon_cmmands_handler::save, this, _1), "Save blockchain");
|
||||||
|
m_cmd_binder.set_handler("set_log", boost::bind(&daemon_cmmands_handler::set_log, this, _1), "set_log <level> - Change current log detalization level, <level> is a number 0-4");
|
||||||
|
m_cmd_binder.set_handler("diff", boost::bind(&daemon_cmmands_handler::diff, this, _1), "Show difficulty");
|
||||||
}
|
}
|
||||||
|
|
||||||
bool start_handling()
|
bool start_handling()
|
||||||
|
@ -54,6 +57,7 @@ private:
|
||||||
std::string get_commands_str()
|
std::string get_commands_str()
|
||||||
{
|
{
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
ss << CRYPTONOTE_NAME << " v" << PROJECT_VERSION_LONG << ENDL;
|
||||||
ss << "Commands: " << ENDL;
|
ss << "Commands: " << ENDL;
|
||||||
std::string usage = m_cmd_binder.get_usage();
|
std::string usage = m_cmd_binder.get_usage();
|
||||||
boost::replace_all(usage, "\n", "\n ");
|
boost::replace_all(usage, "\n", "\n ");
|
||||||
|
@ -98,6 +102,17 @@ private:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
|
bool diff(const std::vector<std::string>& args)
|
||||||
|
{
|
||||||
|
cryptonote::difficulty_type difficulty = m_srv.get_payload_object().get_core().get_blockchain_storage().get_difficulty_for_next_block();
|
||||||
|
uint64_t height = m_srv.get_payload_object().get_core().get_blockchain_storage().get_current_blockchain_height();
|
||||||
|
|
||||||
|
LOG_PRINT_GREEN("BH: " << height << ", DIFF: " << difficulty
|
||||||
|
<< ", HR: " << (int) difficulty / 60L << " H/s", LOG_LEVEL_0);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//--------------------------------------------------------------------------------
|
||||||
bool print_bc_outs(const std::vector<std::string>& args)
|
bool print_bc_outs(const std::vector<std::string>& args)
|
||||||
{
|
{
|
||||||
if(args.size() != 1)
|
if(args.size() != 1)
|
||||||
|
@ -123,19 +138,34 @@ private:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
uint64_t start_index = 0;
|
uint64_t start_index = 0;
|
||||||
|
uint64_t end_index = 0;
|
||||||
uint64_t end_block_parametr = m_srv.get_payload_object().get_core().get_current_blockchain_height();
|
uint64_t end_block_parametr = m_srv.get_payload_object().get_core().get_current_blockchain_height();
|
||||||
if(!string_tools::get_xtype_from_string(start_index, args[0]))
|
if(!string_tools::get_xtype_from_string(start_index, args[0]))
|
||||||
{
|
{
|
||||||
std::cout << "wrong starter block index parameter" << ENDL;
|
std::cout << "wrong starter block index parameter" << ENDL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if(args.size() >1 && !string_tools::get_xtype_from_string(end_block_parametr, args[1]))
|
if(args.size() >1 && !string_tools::get_xtype_from_string(end_index, args[1]))
|
||||||
{
|
{
|
||||||
std::cout << "wrong end block index parameter" << ENDL;
|
std::cout << "wrong end block index parameter" << ENDL;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (end_index == 0)
|
||||||
|
{
|
||||||
|
end_index = end_block_parametr;
|
||||||
|
}
|
||||||
|
if (end_index > end_block_parametr)
|
||||||
|
{
|
||||||
|
std::cout << "end block index parameter shouldn't be greater than " << end_block_parametr << ENDL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (end_index <= start_index)
|
||||||
|
{
|
||||||
|
std::cout << "end block index should be greater than starter block index" << ENDL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
m_srv.get_payload_object().get_core().print_blockchain(start_index, end_block_parametr);
|
m_srv.get_payload_object().get_core().print_blockchain(start_index, end_index);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
|
@ -144,6 +174,33 @@ private:
|
||||||
m_srv.get_payload_object().get_core().print_blockchain_index();
|
m_srv.get_payload_object().get_core().print_blockchain_index();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool set_log(const std::vector<std::string>& args)
|
||||||
|
{
|
||||||
|
if(args.size() != 1)
|
||||||
|
{
|
||||||
|
std::cout << "use: set_log <log_level_number_0-4>" << ENDL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t l = 0;
|
||||||
|
if(!string_tools::get_xtype_from_string(l, args[0]))
|
||||||
|
{
|
||||||
|
std::cout << "wrong number format, use: set_log <log_level_number_0-4>" << ENDL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(LOG_LEVEL_4 < l)
|
||||||
|
{
|
||||||
|
std::cout << "wrong number range, use: set_log <log_level_number_0-4>" << ENDL;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_space::log_singletone::get_set_log_detalisation_level(true, l);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
//--------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static bool print_as_json(T& obj)
|
static bool print_as_json(T& obj)
|
||||||
|
|
|
@ -109,7 +109,7 @@ namespace mining
|
||||||
if(!m_http_client.is_connected())
|
if(!m_http_client.is_connected())
|
||||||
{
|
{
|
||||||
LOG_PRINT_L0("Connecting " << m_pool_ip << ":" << m_pool_port << "....");
|
LOG_PRINT_L0("Connecting " << m_pool_ip << ":" << m_pool_port << "....");
|
||||||
if(!m_http_client.connect(m_pool_ip, m_pool_port, 1000))
|
if(!m_http_client.connect(m_pool_ip, m_pool_port, 20000))
|
||||||
{
|
{
|
||||||
LOG_PRINT_L0("Failed to connect " << m_pool_ip << ":" << m_pool_port << ", sleep....");
|
LOG_PRINT_L0("Failed to connect " << m_pool_ip << ":" << m_pool_port << ", sleep....");
|
||||||
epee::misc_utils::sleep_no_w(1000);
|
epee::misc_utils::sleep_no_w(1000);
|
||||||
|
@ -198,7 +198,7 @@ namespace mining
|
||||||
LOG_PRINT_L0("Can't get new job! Disconnect and sleep....");
|
LOG_PRINT_L0("Can't get new job! Disconnect and sleep....");
|
||||||
m_http_client.disconnect();
|
m_http_client.disconnect();
|
||||||
epee::misc_utils::sleep_no_w(1000);
|
epee::misc_utils::sleep_no_w(1000);
|
||||||
break;
|
continue;
|
||||||
}
|
}
|
||||||
if (getjob_response.blob.empty() && getjob_response.target.empty() && getjob_response.job_id.empty())
|
if (getjob_response.blob.empty() && getjob_response.target.empty() && getjob_response.job_id.empty())
|
||||||
{
|
{
|
||||||
|
|
|
@ -24,8 +24,7 @@
|
||||||
#include "p2p_networks.h"
|
#include "p2p_networks.h"
|
||||||
#include "math_helper.h"
|
#include "math_helper.h"
|
||||||
#include "net_node_common.h"
|
#include "net_node_common.h"
|
||||||
|
#include "common/command_line.h"
|
||||||
using namespace epee;
|
|
||||||
|
|
||||||
PUSH_WARNINGS
|
PUSH_WARNINGS
|
||||||
DISABLE_VS_WARNINGS(4355)
|
DISABLE_VS_WARNINGS(4355)
|
||||||
|
@ -39,7 +38,7 @@ namespace nodetool
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
class node_server: public levin::levin_commands_handler<p2p_connection_context_t<typename t_payload_net_handler::connection_context> >,
|
class node_server: public epee::levin::levin_commands_handler<p2p_connection_context_t<typename t_payload_net_handler::connection_context> >,
|
||||||
public i_p2p_endpoint<typename t_payload_net_handler::connection_context>
|
public i_p2p_endpoint<typename t_payload_net_handler::connection_context>
|
||||||
{
|
{
|
||||||
struct by_conn_id{};
|
struct by_conn_id{};
|
||||||
|
@ -126,7 +125,7 @@ namespace nodetool
|
||||||
bool parse_peer_from_string(nodetool::net_address& pe, const std::string& node_addr);
|
bool parse_peer_from_string(nodetool::net_address& pe, const std::string& node_addr);
|
||||||
bool handle_command_line(const boost::program_options::variables_map& vm);
|
bool handle_command_line(const boost::program_options::variables_map& vm);
|
||||||
bool idle_worker();
|
bool idle_worker();
|
||||||
bool handle_remote_peerlist(const std::list<peerlist_entry>& peerlist, time_t local_time, const net_utils::connection_context_base& context);
|
bool handle_remote_peerlist(const std::list<peerlist_entry>& peerlist, time_t local_time, const epee::net_utils::connection_context_base& context);
|
||||||
bool get_local_node_data(basic_node_data& node_data);
|
bool get_local_node_data(basic_node_data& node_data);
|
||||||
//bool get_local_handshake_data(handshake_data& hshd);
|
//bool get_local_handshake_data(handshake_data& hshd);
|
||||||
|
|
||||||
|
@ -136,7 +135,7 @@ namespace nodetool
|
||||||
bool connections_maker();
|
bool connections_maker();
|
||||||
bool peer_sync_idle_maker();
|
bool peer_sync_idle_maker();
|
||||||
bool do_handshake_with_peer(peerid_type& pi, p2p_connection_context& context, bool just_take_peerlist = false);
|
bool do_handshake_with_peer(peerid_type& pi, p2p_connection_context& context, bool just_take_peerlist = false);
|
||||||
bool do_peer_timed_sync(const net_utils::connection_context_base& context, peerid_type peer_id);
|
bool do_peer_timed_sync(const epee::net_utils::connection_context_base& context, peerid_type peer_id);
|
||||||
|
|
||||||
bool make_new_connection_from_peerlist(bool use_white_list);
|
bool make_new_connection_from_peerlist(bool use_white_list);
|
||||||
bool try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist = false, uint64_t last_seen_stamp = 0, bool white = true);
|
bool try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist = false, uint64_t last_seen_stamp = 0, bool white = true);
|
||||||
|
@ -146,12 +145,19 @@ namespace nodetool
|
||||||
template<class t_callback>
|
template<class t_callback>
|
||||||
bool try_ping(basic_node_data& node_data, p2p_connection_context& context, t_callback cb);
|
bool try_ping(basic_node_data& node_data, p2p_connection_context& context, t_callback cb);
|
||||||
bool make_expected_connections_count(bool white_list, size_t expected_connections);
|
bool make_expected_connections_count(bool white_list, size_t expected_connections);
|
||||||
|
bool is_priority_node(const net_address& na);
|
||||||
|
|
||||||
|
template <class Container>
|
||||||
|
bool connect_to_peerlist(const Container& peers);
|
||||||
|
|
||||||
|
template <class Container>
|
||||||
|
bool parse_peers_and_add_to_container(const boost::program_options::variables_map& vm, const command_line::arg_descriptor<std::vector<std::string> > & arg, Container& container);
|
||||||
|
|
||||||
//debug functions
|
//debug functions
|
||||||
std::string print_connections_container();
|
std::string print_connections_container();
|
||||||
|
|
||||||
|
|
||||||
typedef net_utils::boosted_tcp_server<levin::async_protocol_handler<p2p_connection_context> > net_server;
|
typedef epee::net_utils::boosted_tcp_server<epee::levin::async_protocol_handler<p2p_connection_context> > net_server;
|
||||||
|
|
||||||
struct config
|
struct config
|
||||||
{
|
{
|
||||||
|
@ -181,9 +187,9 @@ namespace nodetool
|
||||||
t_payload_net_handler& m_payload_handler;
|
t_payload_net_handler& m_payload_handler;
|
||||||
peerlist_manager m_peerlist;
|
peerlist_manager m_peerlist;
|
||||||
|
|
||||||
math_helper::once_a_time_seconds<P2P_DEFAULT_HANDSHAKE_INTERVAL> m_peer_handshake_idle_maker_interval;
|
epee::math_helper::once_a_time_seconds<P2P_DEFAULT_HANDSHAKE_INTERVAL> m_peer_handshake_idle_maker_interval;
|
||||||
math_helper::once_a_time_seconds<1> m_connections_maker_interval;
|
epee::math_helper::once_a_time_seconds<1> m_connections_maker_interval;
|
||||||
math_helper::once_a_time_seconds<60*30, false> m_peerlist_store_interval;
|
epee::math_helper::once_a_time_seconds<60*30, false> m_peerlist_store_interval;
|
||||||
|
|
||||||
std::string m_bind_ip;
|
std::string m_bind_ip;
|
||||||
std::string m_port;
|
std::string m_port;
|
||||||
|
@ -191,6 +197,7 @@ namespace nodetool
|
||||||
uint64_t m_last_stat_request_time;
|
uint64_t m_last_stat_request_time;
|
||||||
#endif
|
#endif
|
||||||
std::list<net_address> m_priority_peers;
|
std::list<net_address> m_priority_peers;
|
||||||
|
std::vector<net_address> m_exclusive_peers;
|
||||||
std::vector<net_address> m_seed_nodes;
|
std::vector<net_address> m_seed_nodes;
|
||||||
std::list<nodetool::peerlist_entry> m_command_line_peers;
|
std::list<nodetool::peerlist_entry> m_command_line_peers;
|
||||||
uint64_t m_peer_livetime;
|
uint64_t m_peer_livetime;
|
||||||
|
|
|
@ -4,9 +4,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "string_tools.h"
|
#include "string_tools.h"
|
||||||
#include "common/command_line.h"
|
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
#include "net/net_helper.h"
|
#include "net/net_helper.h"
|
||||||
#include "math_helper.h"
|
#include "math_helper.h"
|
||||||
|
@ -31,8 +32,11 @@ namespace nodetool
|
||||||
const command_line::arg_descriptor<bool> arg_p2p_allow_local_ip = {"allow-local-ip", "Allow local ip add to peer list, mostly in debug purposes"};
|
const command_line::arg_descriptor<bool> arg_p2p_allow_local_ip = {"allow-local-ip", "Allow local ip add to peer list, mostly in debug purposes"};
|
||||||
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_peer = {"add-peer", "Manually add peer to local peerlist"};
|
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_peer = {"add-peer", "Manually add peer to local peerlist"};
|
||||||
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_priority_node = {"add-priority-node", "Specify list of peers to connect to and attempt to keep the connection open"};
|
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_priority_node = {"add-priority-node", "Specify list of peers to connect to and attempt to keep the connection open"};
|
||||||
|
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_add_exclusive_node = {"add-exclusive-node", "Specify list of peers to connect to only."
|
||||||
|
" If this option is given the options add-priority-node and seed-node are ignored"};
|
||||||
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_seed_node = {"seed-node", "Connect to a node to retrieve peer addresses, and disconnect"};
|
const command_line::arg_descriptor<std::vector<std::string> > arg_p2p_seed_node = {"seed-node", "Connect to a node to retrieve peer addresses, and disconnect"};
|
||||||
const command_line::arg_descriptor<bool> arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true}; }
|
const command_line::arg_descriptor<bool> arg_p2p_hide_my_port = {"hide-my-port", "Do not announce yourself as peerlist candidate", false, true};
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
|
@ -44,6 +48,7 @@ namespace nodetool
|
||||||
command_line::add_arg(desc, arg_p2p_allow_local_ip);
|
command_line::add_arg(desc, arg_p2p_allow_local_ip);
|
||||||
command_line::add_arg(desc, arg_p2p_add_peer);
|
command_line::add_arg(desc, arg_p2p_add_peer);
|
||||||
command_line::add_arg(desc, arg_p2p_add_priority_node);
|
command_line::add_arg(desc, arg_p2p_add_priority_node);
|
||||||
|
command_line::add_arg(desc, arg_p2p_add_exclusive_node);
|
||||||
command_line::add_arg(desc, arg_p2p_seed_node);
|
command_line::add_arg(desc, arg_p2p_seed_node);
|
||||||
command_line::add_arg(desc, arg_p2p_hide_my_port); }
|
command_line::add_arg(desc, arg_p2p_hide_my_port); }
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
|
@ -96,7 +101,7 @@ namespace nodetool
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
bool node_server<t_payload_net_handler>::parse_peer_from_string(nodetool::net_address& pe, const std::string& node_addr)
|
bool node_server<t_payload_net_handler>::parse_peer_from_string(nodetool::net_address& pe, const std::string& node_addr)
|
||||||
{
|
{
|
||||||
return string_tools::parse_peer_from_string(pe.ip, pe.port, node_addr);
|
return epee::string_tools::parse_peer_from_string(pe.ip, pe.port, node_addr);
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
|
@ -120,30 +125,26 @@ namespace nodetool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command_line::has_arg(vm, arg_p2p_add_priority_node))
|
if (command_line::has_arg(vm,arg_p2p_add_exclusive_node))
|
||||||
{
|
{
|
||||||
std::vector<std::string> perrs = command_line::get_arg(vm, arg_p2p_add_priority_node);
|
if (!parse_peers_and_add_to_container(vm, arg_p2p_add_exclusive_node, m_exclusive_peers))
|
||||||
for(const std::string& pr_str: perrs)
|
return false;
|
||||||
{
|
}
|
||||||
nodetool::net_address na = AUTO_VAL_INIT(na);
|
else if (command_line::has_arg(vm, arg_p2p_add_priority_node))
|
||||||
bool r = parse_peer_from_string(na, pr_str);
|
{
|
||||||
CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str);
|
if (!parse_peers_and_add_to_container(vm, arg_p2p_add_priority_node, m_priority_peers))
|
||||||
m_priority_peers.push_back(na);
|
return false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (command_line::has_arg(vm, arg_p2p_seed_node))
|
if (command_line::has_arg(vm, arg_p2p_seed_node))
|
||||||
{
|
{
|
||||||
std::vector<std::string> seed_perrs = command_line::get_arg(vm, arg_p2p_seed_node);
|
if (!parse_peers_and_add_to_container(vm, arg_p2p_seed_node, m_seed_nodes))
|
||||||
for(const std::string& pr_str: seed_perrs)
|
return false;
|
||||||
{
|
|
||||||
nodetool::net_address na = AUTO_VAL_INIT(na);
|
|
||||||
bool r = parse_peer_from_string(na, pr_str);
|
|
||||||
CHECK_AND_ASSERT_MES(r, false, "Failed to parse seed address from string: " << pr_str);
|
|
||||||
m_seed_nodes.push_back(na);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(command_line::has_arg(vm, arg_p2p_hide_my_port))
|
if(command_line::has_arg(vm, arg_p2p_hide_my_port))
|
||||||
m_hide_my_port = true; return true;
|
m_hide_my_port = true;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
namespace
|
namespace
|
||||||
|
@ -192,6 +193,15 @@ namespace nodetool
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
bool node_server<t_payload_net_handler>::init(const boost::program_options::variables_map& vm)
|
bool node_server<t_payload_net_handler>::init(const boost::program_options::variables_map& vm)
|
||||||
{
|
{
|
||||||
|
ADD_HARDCODED_SEED_NODE("62.210.78.186:18080");
|
||||||
|
ADD_HARDCODED_SEED_NODE("195.12.60.154:18080");
|
||||||
|
ADD_HARDCODED_SEED_NODE("54.241.246.125:18080");
|
||||||
|
ADD_HARDCODED_SEED_NODE("107.170.157.169:18080");
|
||||||
|
ADD_HARDCODED_SEED_NODE("54.207.112.216:18080");
|
||||||
|
ADD_HARDCODED_SEED_NODE("78.27.112.54:18080");
|
||||||
|
ADD_HARDCODED_SEED_NODE("209.222.30.57:18080");
|
||||||
|
ADD_HARDCODED_SEED_NODE("80.71.13.55:18080");
|
||||||
|
ADD_HARDCODED_SEED_NODE("107.178.112.126:18080");
|
||||||
ADD_HARDCODED_SEED_NODE("107.158.233.98:18080");
|
ADD_HARDCODED_SEED_NODE("107.158.233.98:18080");
|
||||||
ADD_HARDCODED_SEED_NODE("64.22.111.2:18080");
|
ADD_HARDCODED_SEED_NODE("64.22.111.2:18080");
|
||||||
|
|
||||||
|
@ -353,23 +363,23 @@ namespace nodetool
|
||||||
get_local_node_data(arg.node_data);
|
get_local_node_data(arg.node_data);
|
||||||
m_payload_handler.get_payload_sync_data(arg.payload_data);
|
m_payload_handler.get_payload_sync_data(arg.payload_data);
|
||||||
|
|
||||||
simple_event ev;
|
epee::simple_event ev;
|
||||||
std::atomic<bool> hsh_result(false);
|
std::atomic<bool> hsh_result(false);
|
||||||
|
|
||||||
bool r = net_utils::async_invoke_remote_command2<typename COMMAND_HANDSHAKE::response>(context_.m_connection_id, COMMAND_HANDSHAKE::ID, arg, m_net_server.get_config_object(),
|
bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_HANDSHAKE::response>(context_.m_connection_id, COMMAND_HANDSHAKE::ID, arg, m_net_server.get_config_object(),
|
||||||
[this, &pi, &ev, &hsh_result, &just_take_peerlist](int code, const typename COMMAND_HANDSHAKE::response& rsp, p2p_connection_context& context)
|
[this, &pi, &ev, &hsh_result, &just_take_peerlist](int code, const typename COMMAND_HANDSHAKE::response& rsp, p2p_connection_context& context)
|
||||||
{
|
{
|
||||||
misc_utils::auto_scope_leave_caller scope_exit_handler = misc_utils::create_scope_leave_handler([&](){ev.raise();});
|
epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([&](){ev.raise();});
|
||||||
|
|
||||||
if(code < 0)
|
if(code < 0)
|
||||||
{
|
{
|
||||||
LOG_PRINT_CC_RED(context, "COMMAND_HANDSHAKE invoke failed. (" << code << ", " << levin::get_err_descr(code) << ")", LOG_LEVEL_1);
|
LOG_PRINT_CC_RED(context, "COMMAND_HANDSHAKE invoke failed. (" << code << ", " << epee::levin::get_err_descr(code) << ")", LOG_LEVEL_1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rsp.node_data.network_id != BYTECOIN_NETWORK)
|
if(rsp.node_data.network_id != BYTECOIN_NETWORK)
|
||||||
{
|
{
|
||||||
LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong network! (" << string_tools::get_str_from_guid_a(rsp.node_data.network_id) << "), closing connection.");
|
LOG_ERROR_CCONTEXT("COMMAND_HANDSHAKE Failed, wrong network! (" << epee::string_tools::get_str_from_guid_a(rsp.node_data.network_id) << "), closing connection.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,10 +407,10 @@ namespace nodetool
|
||||||
hsh_result = false;
|
hsh_result = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG_PRINT_CCONTEXT_L0(" COMMAND_HANDSHAKE INVOKED OK");
|
LOG_PRINT_CCONTEXT_L1(" COMMAND_HANDSHAKE INVOKED OK");
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
LOG_PRINT_CCONTEXT_L0(" COMMAND_HANDSHAKE(AND CLOSE) INVOKED OK");
|
LOG_PRINT_CCONTEXT_L1(" COMMAND_HANDSHAKE(AND CLOSE) INVOKED OK");
|
||||||
}
|
}
|
||||||
}, P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT);
|
}, P2P_DEFAULT_HANDSHAKE_INVOKE_TIMEOUT);
|
||||||
|
|
||||||
|
@ -411,7 +421,7 @@ namespace nodetool
|
||||||
|
|
||||||
if(!hsh_result)
|
if(!hsh_result)
|
||||||
{
|
{
|
||||||
LOG_PRINT_CC_L0(context_, "COMMAND_HANDSHAKE Failed");
|
LOG_PRINT_CC_L1(context_, "COMMAND_HANDSHAKE Failed");
|
||||||
m_net_server.get_config_object().close(context_.m_connection_id);
|
m_net_server.get_config_object().close(context_.m_connection_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -419,17 +429,17 @@ namespace nodetool
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
bool node_server<t_payload_net_handler>::do_peer_timed_sync(const net_utils::connection_context_base& context_, peerid_type peer_id)
|
bool node_server<t_payload_net_handler>::do_peer_timed_sync(const epee::net_utils::connection_context_base& context_, peerid_type peer_id)
|
||||||
{
|
{
|
||||||
typename COMMAND_TIMED_SYNC::request arg = AUTO_VAL_INIT(arg);
|
typename COMMAND_TIMED_SYNC::request arg = AUTO_VAL_INIT(arg);
|
||||||
m_payload_handler.get_payload_sync_data(arg.payload_data);
|
m_payload_handler.get_payload_sync_data(arg.payload_data);
|
||||||
|
|
||||||
bool r = net_utils::async_invoke_remote_command2<typename COMMAND_TIMED_SYNC::response>(context_.m_connection_id, COMMAND_TIMED_SYNC::ID, arg, m_net_server.get_config_object(),
|
bool r = epee::net_utils::async_invoke_remote_command2<typename COMMAND_TIMED_SYNC::response>(context_.m_connection_id, COMMAND_TIMED_SYNC::ID, arg, m_net_server.get_config_object(),
|
||||||
[this](int code, const typename COMMAND_TIMED_SYNC::response& rsp, p2p_connection_context& context)
|
[this](int code, const typename COMMAND_TIMED_SYNC::response& rsp, p2p_connection_context& context)
|
||||||
{
|
{
|
||||||
if(code < 0)
|
if(code < 0)
|
||||||
{
|
{
|
||||||
LOG_PRINT_CC_RED(context, "COMMAND_TIMED_SYNC invoke failed. (" << code << ", " << levin::get_err_descr(code) << ")", LOG_LEVEL_1);
|
LOG_PRINT_CC_RED(context, "COMMAND_TIMED_SYNC invoke failed. (" << code << ", " << epee::levin::get_err_descr(code) << ")", LOG_LEVEL_1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -502,36 +512,53 @@ namespace nodetool
|
||||||
return connected;
|
return connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
#define LOG_PRINT_CC_PRIORITY_NODE(priority, con, msg) \
|
||||||
|
do { \
|
||||||
|
if (priority) {\
|
||||||
|
LOG_PRINT_CC_L0(con, msg); \
|
||||||
|
} else {\
|
||||||
|
LOG_PRINT_CC_L1(con, msg); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
bool node_server<t_payload_net_handler>::try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist, uint64_t last_seen_stamp, bool white)
|
bool node_server<t_payload_net_handler>::try_to_connect_and_handshake_with_new_peer(const net_address& na, bool just_take_peerlist, uint64_t last_seen_stamp, bool white)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L0("Connecting to " << string_tools::get_ip_string_from_int32(na.ip) << ":" << string_tools::num_to_string_fast(na.port) << "(white=" << white << ", last_seen: " << (last_seen_stamp?misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp):"never" ) << ")...");
|
LOG_PRINT_L1("Connecting to " << epee::string_tools::get_ip_string_from_int32(na.ip) << ":"
|
||||||
|
<< epee::string_tools::num_to_string_fast(na.port) << "(white=" << white << ", last_seen: "
|
||||||
|
<< (last_seen_stamp ? epee::misc_utils::get_time_interval_string(time(NULL) - last_seen_stamp):"never")
|
||||||
|
<< ")...");
|
||||||
|
|
||||||
typename net_server::t_connection_context con = AUTO_VAL_INIT(con);
|
typename net_server::t_connection_context con = AUTO_VAL_INIT(con);
|
||||||
bool res = m_net_server.connect(string_tools::get_ip_string_from_int32(na.ip),
|
bool res = m_net_server.connect(epee::string_tools::get_ip_string_from_int32(na.ip),
|
||||||
string_tools::num_to_string_fast(na.port),
|
epee::string_tools::num_to_string_fast(na.port),
|
||||||
m_config.m_net_config.connection_timeout,
|
m_config.m_net_config.connection_timeout,
|
||||||
con);
|
con);
|
||||||
|
|
||||||
if(!res)
|
if(!res)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L0("Connect failed to "
|
bool is_priority = is_priority_node(na);
|
||||||
<< string_tools::get_ip_string_from_int32(na.ip)
|
LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Connect failed to "
|
||||||
<< ":" << string_tools::num_to_string_fast(na.port)
|
<< epee::string_tools::get_ip_string_from_int32(na.ip)
|
||||||
|
<< ":" << epee::string_tools::num_to_string_fast(na.port)
|
||||||
/*<< ", try " << try_count*/);
|
/*<< ", try " << try_count*/);
|
||||||
//m_peerlist.set_peer_unreachable(pe);
|
//m_peerlist.set_peer_unreachable(pe);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
peerid_type pi = AUTO_VAL_INIT(pi);
|
peerid_type pi = AUTO_VAL_INIT(pi);
|
||||||
res = do_handshake_with_peer(pi, con, just_take_peerlist);
|
res = do_handshake_with_peer(pi, con, just_take_peerlist);
|
||||||
|
|
||||||
if(!res)
|
if(!res)
|
||||||
{
|
{
|
||||||
LOG_PRINT_CC_L0(con, "Failed to HANDSHAKE with peer "
|
bool is_priority = is_priority_node(na);
|
||||||
<< string_tools::get_ip_string_from_int32(na.ip)
|
LOG_PRINT_CC_PRIORITY_NODE(is_priority, con, "Failed to HANDSHAKE with peer "
|
||||||
<< ":" << string_tools::num_to_string_fast(na.port)
|
<< epee::string_tools::get_ip_string_from_int32(na.ip)
|
||||||
|
<< ":" << epee::string_tools::num_to_string_fast(na.port)
|
||||||
/*<< ", try " << try_count*/);
|
/*<< ", try " << try_count*/);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(just_take_peerlist)
|
if(just_take_peerlist)
|
||||||
{
|
{
|
||||||
m_net_server.get_config_object().close(con.m_connection_id);
|
m_net_server.get_config_object().close(con.m_connection_id);
|
||||||
|
@ -549,6 +576,9 @@ namespace nodetool
|
||||||
LOG_PRINT_CC_GREEN(con, "CONNECTION HANDSHAKED OK.", LOG_LEVEL_2);
|
LOG_PRINT_CC_GREEN(con, "CONNECTION HANDSHAKED OK.", LOG_LEVEL_2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#undef LOG_PRINT_CC_PRIORITY_NODE
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
bool node_server<t_payload_net_handler>::make_new_connection_from_peerlist(bool use_white_list)
|
bool node_server<t_payload_net_handler>::make_new_connection_from_peerlist(bool use_white_list)
|
||||||
|
@ -582,7 +612,10 @@ namespace nodetool
|
||||||
if(is_peer_used(pe))
|
if(is_peer_used(pe))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
LOG_PRINT_L1("Selected peer: " << pe.id << " " << string_tools::get_ip_string_from_int32(pe.adr.ip) << ":" << boost::lexical_cast<std::string>(pe.adr.port) << "[white=" << use_white_list << "] last_seen: " << (pe.last_seen ? misc_utils::get_time_interval_string(time(NULL) - pe.last_seen) : "never"));
|
LOG_PRINT_L1("Selected peer: " << pe.id << " " << epee::string_tools::get_ip_string_from_int32(pe.adr.ip)
|
||||||
|
<< ":" << boost::lexical_cast<std::string>(pe.adr.port)
|
||||||
|
<< "[white=" << use_white_list
|
||||||
|
<< "] last_seen: " << (pe.last_seen ? epee::misc_utils::get_time_interval_string(time(NULL) - pe.last_seen) : "never"));
|
||||||
|
|
||||||
if(!try_to_connect_and_handshake_with_new_peer(pe.adr, false, pe.last_seen, use_white_list))
|
if(!try_to_connect_and_handshake_with_new_peer(pe.adr, false, pe.last_seen, use_white_list))
|
||||||
continue;
|
continue;
|
||||||
|
@ -595,6 +628,10 @@ namespace nodetool
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
bool node_server<t_payload_net_handler>::connections_maker()
|
bool node_server<t_payload_net_handler>::connections_maker()
|
||||||
{
|
{
|
||||||
|
if (!connect_to_peerlist(m_exclusive_peers)) return false;
|
||||||
|
|
||||||
|
if (!m_exclusive_peers.empty()) return true;
|
||||||
|
|
||||||
if(!m_peerlist.get_white_peers_count() && m_seed_nodes.size())
|
if(!m_peerlist.get_white_peers_count() && m_seed_nodes.size())
|
||||||
{
|
{
|
||||||
size_t try_count = 0;
|
size_t try_count = 0;
|
||||||
|
@ -616,15 +653,7 @@ namespace nodetool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for(const net_address& na: m_priority_peers)
|
if (!connect_to_peerlist(m_priority_peers)) return false;
|
||||||
{
|
|
||||||
if(m_net_server.is_stop_signal_sent())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(is_addr_connected(na))
|
|
||||||
continue;
|
|
||||||
try_to_connect_and_handshake_with_new_peer(na);
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t expected_white_connections = (m_config.m_net_config.connections_count*P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT)/100;
|
size_t expected_white_connections = (m_config.m_net_config.connections_count*P2P_DEFAULT_WHITELIST_CONNECTIONS_PERCENT)/100;
|
||||||
|
|
||||||
|
@ -698,7 +727,7 @@ namespace nodetool
|
||||||
bool node_server<t_payload_net_handler>::peer_sync_idle_maker()
|
bool node_server<t_payload_net_handler>::peer_sync_idle_maker()
|
||||||
{
|
{
|
||||||
LOG_PRINT_L2("STARTED PEERLIST IDLE HANDSHAKE");
|
LOG_PRINT_L2("STARTED PEERLIST IDLE HANDSHAKE");
|
||||||
typedef std::list<std::pair<net_utils::connection_context_base, peerid_type> > local_connects_type;
|
typedef std::list<std::pair<epee::net_utils::connection_context_base, peerid_type> > local_connects_type;
|
||||||
local_connects_type cncts;
|
local_connects_type cncts;
|
||||||
m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
|
m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
|
||||||
{
|
{
|
||||||
|
@ -725,7 +754,7 @@ namespace nodetool
|
||||||
{
|
{
|
||||||
if(be.last_seen > local_time)
|
if(be.last_seen > local_time)
|
||||||
{
|
{
|
||||||
LOG_PRINT_RED_L0("FOUND FUTURE peerlist for entry " << string_tools::get_ip_string_from_int32(be.adr.ip) << ":" << be.adr.port << " last_seen: " << be.last_seen << ", local_time(on remote node):" << local_time);
|
LOG_PRINT_RED_L0("FOUND FUTURE peerlist for entry " << epee::string_tools::get_ip_string_from_int32(be.adr.ip) << ":" << be.adr.port << " last_seen: " << be.last_seen << ", local_time(on remote node):" << local_time);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
be.last_seen += delta;
|
be.last_seen += delta;
|
||||||
|
@ -734,7 +763,7 @@ namespace nodetool
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
bool node_server<t_payload_net_handler>::handle_remote_peerlist(const std::list<peerlist_entry>& peerlist, time_t local_time, const net_utils::connection_context_base& context)
|
bool node_server<t_payload_net_handler>::handle_remote_peerlist(const std::list<peerlist_entry>& peerlist, time_t local_time, const epee::net_utils::connection_context_base& context)
|
||||||
{
|
{
|
||||||
int64_t delta = 0;
|
int64_t delta = 0;
|
||||||
std::list<peerlist_entry> peerlist_ = peerlist;
|
std::list<peerlist_entry> peerlist_ = peerlist;
|
||||||
|
@ -782,7 +811,7 @@ namespace nodetool
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
crypto::public_key pk = AUTO_VAL_INIT(pk);
|
crypto::public_key pk = AUTO_VAL_INIT(pk);
|
||||||
string_tools::hex_to_pod(P2P_STAT_TRUSTED_PUB_KEY, pk);
|
epee::string_tools::hex_to_pod(P2P_STAT_TRUSTED_PUB_KEY, pk);
|
||||||
crypto::hash h = tools::get_proof_of_trust_hash(tr);
|
crypto::hash h = tools::get_proof_of_trust_hash(tr);
|
||||||
if(!crypto::check_signature(h, pk, tr.sign))
|
if(!crypto::check_signature(h, pk, tr.sign))
|
||||||
{
|
{
|
||||||
|
@ -903,8 +932,8 @@ namespace nodetool
|
||||||
uint32_t actual_ip = context.m_remote_ip;
|
uint32_t actual_ip = context.m_remote_ip;
|
||||||
if(!m_peerlist.is_ip_allowed(actual_ip))
|
if(!m_peerlist.is_ip_allowed(actual_ip))
|
||||||
return false;
|
return false;
|
||||||
std::string ip = string_tools::get_ip_string_from_int32(actual_ip);
|
std::string ip = epee::string_tools::get_ip_string_from_int32(actual_ip);
|
||||||
std::string port = string_tools::num_to_string_fast(node_data.my_port);
|
std::string port = epee::string_tools::num_to_string_fast(node_data.my_port);
|
||||||
peerid_type pr = node_data.peer_id;
|
peerid_type pr = node_data.peer_id;
|
||||||
bool r = m_net_server.connect_async(ip, port, m_config.m_net_config.ping_connection_timeout, [cb, /*context,*/ ip, port, pr, this](
|
bool r = m_net_server.connect_async(ip, port, m_config.m_net_config.ping_connection_timeout, [cb, /*context,*/ ip, port, pr, this](
|
||||||
const typename net_server::t_connection_context& ping_context,
|
const typename net_server::t_connection_context& ping_context,
|
||||||
|
@ -922,12 +951,12 @@ namespace nodetool
|
||||||
std::string port_=port;
|
std::string port_=port;
|
||||||
peerid_type pr_ = pr;
|
peerid_type pr_ = pr;
|
||||||
auto cb_ = cb;*/
|
auto cb_ = cb;*/
|
||||||
bool inv_call_res = net_utils::async_invoke_remote_command2<COMMAND_PING::response>(ping_context.m_connection_id, COMMAND_PING::ID, req, m_net_server.get_config_object(),
|
bool inv_call_res = epee::net_utils::async_invoke_remote_command2<COMMAND_PING::response>(ping_context.m_connection_id, COMMAND_PING::ID, req, m_net_server.get_config_object(),
|
||||||
[=](int code, const COMMAND_PING::response& rsp, p2p_connection_context& context)
|
[=](int code, const COMMAND_PING::response& rsp, p2p_connection_context& context)
|
||||||
{
|
{
|
||||||
if(code <= 0)
|
if(code <= 0)
|
||||||
{
|
{
|
||||||
LOG_PRINT_CC_L2(ping_context, "Failed to invoke COMMAND_PING to " << ip << ":" << port << "(" << code << ", " << levin::get_err_descr(code) << ")");
|
LOG_PRINT_CC_L2(ping_context, "Failed to invoke COMMAND_PING to " << ip << ":" << port << "(" << code << ", " << epee::levin::get_err_descr(code) << ")");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -979,7 +1008,7 @@ namespace nodetool
|
||||||
if(arg.node_data.network_id != BYTECOIN_NETWORK)
|
if(arg.node_data.network_id != BYTECOIN_NETWORK)
|
||||||
{
|
{
|
||||||
|
|
||||||
LOG_PRINT_CCONTEXT_L0("WRONG NETWORK AGENT CONNECTED! id=" << string_tools::get_str_from_guid_a(arg.node_data.network_id));
|
LOG_PRINT_CCONTEXT_L0("WRONG NETWORK AGENT CONNECTED! id=" << epee::string_tools::get_str_from_guid_a(arg.node_data.network_id));
|
||||||
drop_connection(context);
|
drop_connection(context);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
@ -1021,7 +1050,7 @@ namespace nodetool
|
||||||
time(&pe.last_seen);
|
time(&pe.last_seen);
|
||||||
pe.id = peer_id_l;
|
pe.id = peer_id_l;
|
||||||
this->m_peerlist.append_with_peer_white(pe);
|
this->m_peerlist.append_with_peer_white(pe);
|
||||||
LOG_PRINT_CCONTEXT_L2("PING SUCCESS " << string_tools::get_ip_string_from_int32(context.m_remote_ip) << ":" << port_l);
|
LOG_PRINT_CCONTEXT_L2("PING SUCCESS " << epee::string_tools::get_ip_string_from_int32(context.m_remote_ip) << ":" << port_l);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1066,9 +1095,9 @@ namespace nodetool
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
|
m_net_server.get_config_object().foreach_connection([&](const p2p_connection_context& cntxt)
|
||||||
{
|
{
|
||||||
ss << string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) << ":" << cntxt.m_remote_port
|
ss << epee::string_tools::get_ip_string_from_int32(cntxt.m_remote_ip) << ":" << cntxt.m_remote_port
|
||||||
<< " \t\tpeer_id " << cntxt.peer_id
|
<< " \t\tpeer_id " << cntxt.peer_id
|
||||||
<< " \t\tconn_id " << string_tools::get_str_from_guid_a(cntxt.m_connection_id) << (cntxt.m_is_income ? " INC":" OUT")
|
<< " \t\tconn_id " << epee::string_tools::get_str_from_guid_a(cntxt.m_connection_id) << (cntxt.m_is_income ? " INC":" OUT")
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -1079,13 +1108,51 @@ namespace nodetool
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
void node_server<t_payload_net_handler>::on_connection_new(p2p_connection_context& context)
|
void node_server<t_payload_net_handler>::on_connection_new(p2p_connection_context& context)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L2("["<< net_utils::print_connection_context(context) << "] NEW CONNECTION");
|
LOG_PRINT_L2("["<< epee::net_utils::print_connection_context(context) << "] NEW CONNECTION");
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
template<class t_payload_net_handler>
|
template<class t_payload_net_handler>
|
||||||
void node_server<t_payload_net_handler>::on_connection_close(p2p_connection_context& context)
|
void node_server<t_payload_net_handler>::on_connection_close(p2p_connection_context& context)
|
||||||
{
|
{
|
||||||
LOG_PRINT_L2("["<< net_utils::print_connection_context(context) << "] CLOSE CONNECTION");
|
LOG_PRINT_L2("["<< epee::net_utils::print_connection_context(context) << "] CLOSE CONNECTION");
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class t_payload_net_handler>
|
||||||
|
bool node_server<t_payload_net_handler>::is_priority_node(const net_address& na)
|
||||||
|
{
|
||||||
|
return (std::find(m_priority_peers.begin(), m_priority_peers.end(), na) != m_priority_peers.end()) || (std::find(m_exclusive_peers.begin(), m_exclusive_peers.end(), na) != m_exclusive_peers.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class t_payload_net_handler> template <class Container>
|
||||||
|
bool node_server<t_payload_net_handler>::connect_to_peerlist(const Container& peers)
|
||||||
|
{
|
||||||
|
for(const net_address& na: peers)
|
||||||
|
{
|
||||||
|
if(m_net_server.is_stop_signal_sent())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(is_addr_connected(na))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
try_to_connect_and_handshake_with_new_peer(na);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class t_payload_net_handler> template <class Container>
|
||||||
|
bool node_server<t_payload_net_handler>::parse_peers_and_add_to_container(const boost::program_options::variables_map& vm, const command_line::arg_descriptor<std::vector<std::string> > & arg, Container& container)
|
||||||
|
{
|
||||||
|
std::vector<std::string> perrs = command_line::get_arg(vm, arg);
|
||||||
|
|
||||||
|
for(const std::string& pr_str: perrs)
|
||||||
|
{
|
||||||
|
nodetool::net_address na = AUTO_VAL_INIT(na);
|
||||||
|
bool r = parse_peer_from_string(na, pr_str);
|
||||||
|
CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str);
|
||||||
|
container.push_back(na);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,24 +48,30 @@ namespace cryptonote
|
||||||
return epee::http_server_impl_base<core_rpc_server, connection_context>::init(m_port, m_bind_ip);
|
return epee::http_server_impl_base<core_rpc_server, connection_context>::init(m_port, m_bind_ip);
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::check_core_ready()
|
bool core_rpc_server::check_core_busy()
|
||||||
{
|
{
|
||||||
if(!m_p2p.get_payload_object().is_synchronized())
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if(m_p2p.get_payload_object().get_core().get_blockchain_storage().is_storing_blockchain())
|
if(m_p2p.get_payload_object().get_core().get_blockchain_storage().is_storing_blockchain())
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
#define CHECK_CORE_BUSY() if(!check_core_busy()){res.status = CORE_RPC_STATUS_BUSY;return true;}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
bool core_rpc_server::check_core_ready()
|
||||||
|
{
|
||||||
|
if(!m_p2p.get_payload_object().is_synchronized())
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return check_core_busy();
|
||||||
|
}
|
||||||
#define CHECK_CORE_READY() if(!check_core_ready()){res.status = CORE_RPC_STATUS_BUSY;return true;}
|
#define CHECK_CORE_READY() if(!check_core_ready()){res.status = CORE_RPC_STATUS_BUSY;return true;}
|
||||||
|
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::on_get_height(const COMMAND_RPC_GET_HEIGHT::request& req, COMMAND_RPC_GET_HEIGHT::response& res, connection_context& cntx)
|
bool core_rpc_server::on_get_height(const COMMAND_RPC_GET_HEIGHT::request& req, COMMAND_RPC_GET_HEIGHT::response& res, connection_context& cntx)
|
||||||
{
|
{
|
||||||
CHECK_CORE_READY();
|
CHECK_CORE_BUSY();
|
||||||
res.height = m_core.get_current_blockchain_height();
|
res.height = m_core.get_current_blockchain_height();
|
||||||
res.status = CORE_RPC_STATUS_OK;
|
res.status = CORE_RPC_STATUS_OK;
|
||||||
return true;
|
return true;
|
||||||
|
@ -73,8 +79,9 @@ namespace cryptonote
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res, connection_context& cntx)
|
bool core_rpc_server::on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res, connection_context& cntx)
|
||||||
{
|
{
|
||||||
CHECK_CORE_READY();
|
CHECK_CORE_BUSY();
|
||||||
res.height = m_core.get_current_blockchain_height();
|
res.height = m_core.get_current_blockchain_height();
|
||||||
|
res.target_height = m_core.get_target_blockchain_height();
|
||||||
res.difficulty = m_core.get_blockchain_storage().get_difficulty_for_next_block();
|
res.difficulty = m_core.get_blockchain_storage().get_difficulty_for_next_block();
|
||||||
res.tx_count = m_core.get_blockchain_storage().get_total_transactions() - res.height; //without coinbase
|
res.tx_count = m_core.get_blockchain_storage().get_total_transactions() - res.height; //without coinbase
|
||||||
res.tx_pool_size = m_core.get_pool_transactions_count();
|
res.tx_pool_size = m_core.get_pool_transactions_count();
|
||||||
|
@ -90,7 +97,7 @@ namespace cryptonote
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res, connection_context& cntx)
|
bool core_rpc_server::on_get_blocks(const COMMAND_RPC_GET_BLOCKS_FAST::request& req, COMMAND_RPC_GET_BLOCKS_FAST::response& res, connection_context& cntx)
|
||||||
{
|
{
|
||||||
CHECK_CORE_READY();
|
CHECK_CORE_BUSY();
|
||||||
std::list<std::pair<block, std::list<transaction> > > bs;
|
std::list<std::pair<block, std::list<transaction> > > bs;
|
||||||
if(!m_core.find_blockchain_supplement(req.block_ids, bs, res.current_height, res.start_height, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT))
|
if(!m_core.find_blockchain_supplement(req.block_ids, bs, res.current_height, res.start_height, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT))
|
||||||
{
|
{
|
||||||
|
@ -114,7 +121,7 @@ namespace cryptonote
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res, connection_context& cntx)
|
bool core_rpc_server::on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res, connection_context& cntx)
|
||||||
{
|
{
|
||||||
CHECK_CORE_READY();
|
CHECK_CORE_BUSY();
|
||||||
res.status = "Failed";
|
res.status = "Failed";
|
||||||
if(!m_core.get_random_outs_for_amounts(req, res))
|
if(!m_core.get_random_outs_for_amounts(req, res))
|
||||||
{
|
{
|
||||||
|
@ -143,7 +150,7 @@ namespace cryptonote
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& res, connection_context& cntx)
|
bool core_rpc_server::on_get_indexes(const COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::request& req, COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES::response& res, connection_context& cntx)
|
||||||
{
|
{
|
||||||
CHECK_CORE_READY();
|
CHECK_CORE_BUSY();
|
||||||
bool r = m_core.get_tx_outputs_gindexs(req.txid, res.o_indexes);
|
bool r = m_core.get_tx_outputs_gindexs(req.txid, res.o_indexes);
|
||||||
if(!r)
|
if(!r)
|
||||||
{
|
{
|
||||||
|
@ -157,7 +164,7 @@ namespace cryptonote
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::request& req, COMMAND_RPC_GET_TRANSACTIONS::response& res, connection_context& cntx)
|
bool core_rpc_server::on_get_transactions(const COMMAND_RPC_GET_TRANSACTIONS::request& req, COMMAND_RPC_GET_TRANSACTIONS::response& res, connection_context& cntx)
|
||||||
{
|
{
|
||||||
CHECK_CORE_READY();
|
CHECK_CORE_BUSY();
|
||||||
std::vector<crypto::hash> vh;
|
std::vector<crypto::hash> vh;
|
||||||
BOOST_FOREACH(const auto& tx_hex_str, req.txs_hashes)
|
BOOST_FOREACH(const auto& tx_hex_str, req.txs_hashes)
|
||||||
{
|
{
|
||||||
|
@ -232,7 +239,6 @@ namespace cryptonote
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
NOTIFY_NEW_TRANSACTIONS::request r;
|
NOTIFY_NEW_TRANSACTIONS::request r;
|
||||||
r.txs.push_back(tx_blob);
|
r.txs.push_back(tx_blob);
|
||||||
m_core.get_protocol()->relay_transactions(r, fake_context);
|
m_core.get_protocol()->relay_transactions(r, fake_context);
|
||||||
|
@ -265,7 +271,6 @@ namespace cryptonote
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res, connection_context& cntx)
|
bool core_rpc_server::on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res, connection_context& cntx)
|
||||||
{
|
{
|
||||||
CHECK_CORE_READY();
|
|
||||||
if(!m_core.get_miner().stop())
|
if(!m_core.get_miner().stop())
|
||||||
{
|
{
|
||||||
res.status = "Failed, mining not stopped";
|
res.status = "Failed, mining not stopped";
|
||||||
|
@ -275,9 +280,39 @@ namespace cryptonote
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res, connection_context& cntx)
|
bool core_rpc_server::on_mining_status(const COMMAND_RPC_MINING_STATUS::request& req, COMMAND_RPC_MINING_STATUS::response& res, connection_context& cntx)
|
||||||
{
|
{
|
||||||
CHECK_CORE_READY();
|
CHECK_CORE_READY();
|
||||||
|
|
||||||
|
const miner& lMiner = m_core.get_miner();
|
||||||
|
res.active = lMiner.is_mining();
|
||||||
|
|
||||||
|
if ( lMiner.is_mining() ) {
|
||||||
|
res.speed = lMiner.get_speed();
|
||||||
|
res.threads_count = lMiner.get_threads_count();
|
||||||
|
const account_public_address& lMiningAdr = lMiner.get_mining_address();
|
||||||
|
res.address = get_account_address_as_str(lMiningAdr);
|
||||||
|
}
|
||||||
|
|
||||||
|
res.status = CORE_RPC_STATUS_OK;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
bool core_rpc_server::on_save_bc(const COMMAND_RPC_SAVE_BC::request& req, COMMAND_RPC_SAVE_BC::response& res, connection_context& cntx)
|
||||||
|
{
|
||||||
|
CHECK_CORE_BUSY();
|
||||||
|
if( !m_core.get_blockchain_storage().store_blockchain() )
|
||||||
|
{
|
||||||
|
res.status = "Error while storing blockhain";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
res.status = CORE_RPC_STATUS_OK;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
bool core_rpc_server::on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res, connection_context& cntx)
|
||||||
|
{
|
||||||
|
CHECK_CORE_BUSY();
|
||||||
res.count = m_core.get_current_blockchain_height();
|
res.count = m_core.get_current_blockchain_height();
|
||||||
res.status = CORE_RPC_STATUS_OK;
|
res.status = CORE_RPC_STATUS_OK;
|
||||||
return true;
|
return true;
|
||||||
|
@ -285,7 +320,7 @@ namespace cryptonote
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::on_getblockhash(const COMMAND_RPC_GETBLOCKHASH::request& req, COMMAND_RPC_GETBLOCKHASH::response& res, epee::json_rpc::error& error_resp, connection_context& cntx)
|
bool core_rpc_server::on_getblockhash(const COMMAND_RPC_GETBLOCKHASH::request& req, COMMAND_RPC_GETBLOCKHASH::response& res, epee::json_rpc::error& error_resp, connection_context& cntx)
|
||||||
{
|
{
|
||||||
if(!check_core_ready())
|
if(!check_core_busy())
|
||||||
{
|
{
|
||||||
error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY;
|
error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY;
|
||||||
error_resp.message = "Core is busy";
|
error_resp.message = "Core is busy";
|
||||||
|
@ -383,7 +418,7 @@ namespace cryptonote
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
res.blocktemplate_blob = string_tools::buff_to_hex_nodelimer(block_blob);
|
res.blocktemplate_blob = string_tools::buff_to_hex_nodelimer(block_blob);
|
||||||
|
res.status = CORE_RPC_STATUS_OK;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -403,15 +438,33 @@ namespace cryptonote
|
||||||
error_resp.message = "Wrong block blob";
|
error_resp.message = "Wrong block blob";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
cryptonote::block_verification_context bvc = AUTO_VAL_INIT(bvc);
|
|
||||||
m_core.handle_incoming_block(blockblob, bvc);
|
// Fixing of high orphan issue for most pools
|
||||||
if(!bvc.m_added_to_main_chain)
|
// Thanks Boolberry!
|
||||||
|
block b = AUTO_VAL_INIT(b);
|
||||||
|
if(!parse_and_validate_block_from_blob(blockblob, b))
|
||||||
|
{
|
||||||
|
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB;
|
||||||
|
error_resp.message = "Wrong block blob";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fix from Boolberry neglects to check block
|
||||||
|
// size, do that with the function below
|
||||||
|
if(!m_core.check_incoming_block_size(blockblob))
|
||||||
|
{
|
||||||
|
error_resp.code = CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB_SIZE;
|
||||||
|
error_resp.message = "Block bloc size is too big, rejecting block";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!m_core.handle_block_found(b))
|
||||||
{
|
{
|
||||||
error_resp.code = CORE_RPC_ERROR_CODE_BLOCK_NOT_ACCEPTED;
|
error_resp.code = CORE_RPC_ERROR_CODE_BLOCK_NOT_ACCEPTED;
|
||||||
error_resp.message = "Block not accepted";
|
error_resp.message = "Block not accepted";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
res.status = "OK";
|
res.status = CORE_RPC_STATUS_OK;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
@ -443,7 +496,7 @@ namespace cryptonote
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::on_get_last_block_header(const COMMAND_RPC_GET_LAST_BLOCK_HEADER::request& req, COMMAND_RPC_GET_LAST_BLOCK_HEADER::response& res, epee::json_rpc::error& error_resp, connection_context& cntx)
|
bool core_rpc_server::on_get_last_block_header(const COMMAND_RPC_GET_LAST_BLOCK_HEADER::request& req, COMMAND_RPC_GET_LAST_BLOCK_HEADER::response& res, epee::json_rpc::error& error_resp, connection_context& cntx)
|
||||||
{
|
{
|
||||||
if(!check_core_ready())
|
if(!check_core_busy())
|
||||||
{
|
{
|
||||||
error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY;
|
error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY;
|
||||||
error_resp.message = "Core is busy.";
|
error_resp.message = "Core is busy.";
|
||||||
|
@ -478,7 +531,7 @@ namespace cryptonote
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::on_get_block_header_by_hash(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::response& res, epee::json_rpc::error& error_resp, connection_context& cntx){
|
bool core_rpc_server::on_get_block_header_by_hash(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HASH::response& res, epee::json_rpc::error& error_resp, connection_context& cntx){
|
||||||
if(!check_core_ready())
|
if(!check_core_busy())
|
||||||
{
|
{
|
||||||
error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY;
|
error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY;
|
||||||
error_resp.message = "Core is busy.";
|
error_resp.message = "Core is busy.";
|
||||||
|
@ -519,7 +572,7 @@ namespace cryptonote
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool core_rpc_server::on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response& res, epee::json_rpc::error& error_resp, connection_context& cntx){
|
bool core_rpc_server::on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response& res, epee::json_rpc::error& error_resp, connection_context& cntx){
|
||||||
if(!check_core_ready())
|
if(!check_core_busy())
|
||||||
{
|
{
|
||||||
error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY;
|
error_resp.code = CORE_RPC_ERROR_CODE_CORE_BUSY;
|
||||||
error_resp.message = "Core is busy.";
|
error_resp.message = "Core is busy.";
|
||||||
|
|
|
@ -40,6 +40,8 @@ namespace cryptonote
|
||||||
MAP_URI_AUTO_JON2("/sendrawtransaction", on_send_raw_tx, COMMAND_RPC_SEND_RAW_TX)
|
MAP_URI_AUTO_JON2("/sendrawtransaction", on_send_raw_tx, COMMAND_RPC_SEND_RAW_TX)
|
||||||
MAP_URI_AUTO_JON2("/start_mining", on_start_mining, COMMAND_RPC_START_MINING)
|
MAP_URI_AUTO_JON2("/start_mining", on_start_mining, COMMAND_RPC_START_MINING)
|
||||||
MAP_URI_AUTO_JON2("/stop_mining", on_stop_mining, COMMAND_RPC_STOP_MINING)
|
MAP_URI_AUTO_JON2("/stop_mining", on_stop_mining, COMMAND_RPC_STOP_MINING)
|
||||||
|
MAP_URI_AUTO_JON2("/mining_status", on_mining_status, COMMAND_RPC_MINING_STATUS)
|
||||||
|
MAP_URI_AUTO_JON2("/save_bc", on_save_bc, COMMAND_RPC_SAVE_BC)
|
||||||
MAP_URI_AUTO_JON2("/getinfo", on_get_info, COMMAND_RPC_GET_INFO)
|
MAP_URI_AUTO_JON2("/getinfo", on_get_info, COMMAND_RPC_GET_INFO)
|
||||||
BEGIN_JSON_RPC_MAP("/json_rpc")
|
BEGIN_JSON_RPC_MAP("/json_rpc")
|
||||||
MAP_JON_RPC("getblockcount", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT)
|
MAP_JON_RPC("getblockcount", on_getblockcount, COMMAND_RPC_GETBLOCKCOUNT)
|
||||||
|
@ -59,8 +61,10 @@ namespace cryptonote
|
||||||
bool on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request& req, COMMAND_RPC_SEND_RAW_TX::response& res, connection_context& cntx);
|
bool on_send_raw_tx(const COMMAND_RPC_SEND_RAW_TX::request& req, COMMAND_RPC_SEND_RAW_TX::response& res, connection_context& cntx);
|
||||||
bool on_start_mining(const COMMAND_RPC_START_MINING::request& req, COMMAND_RPC_START_MINING::response& res, connection_context& cntx);
|
bool on_start_mining(const COMMAND_RPC_START_MINING::request& req, COMMAND_RPC_START_MINING::response& res, connection_context& cntx);
|
||||||
bool on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res, connection_context& cntx);
|
bool on_stop_mining(const COMMAND_RPC_STOP_MINING::request& req, COMMAND_RPC_STOP_MINING::response& res, connection_context& cntx);
|
||||||
|
bool on_mining_status(const COMMAND_RPC_MINING_STATUS::request& req, COMMAND_RPC_MINING_STATUS::response& res, connection_context& cntx);
|
||||||
bool on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res, connection_context& cntx);
|
bool on_get_random_outs(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res, connection_context& cntx);
|
||||||
bool on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res, connection_context& cntx);
|
bool on_get_info(const COMMAND_RPC_GET_INFO::request& req, COMMAND_RPC_GET_INFO::response& res, connection_context& cntx);
|
||||||
|
bool on_save_bc(const COMMAND_RPC_SAVE_BC::request& req, COMMAND_RPC_SAVE_BC::response& res, connection_context& cntx);
|
||||||
|
|
||||||
//json_rpc
|
//json_rpc
|
||||||
bool on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res, connection_context& cntx);
|
bool on_getblockcount(const COMMAND_RPC_GETBLOCKCOUNT::request& req, COMMAND_RPC_GETBLOCKCOUNT::response& res, connection_context& cntx);
|
||||||
|
@ -72,6 +76,7 @@ namespace cryptonote
|
||||||
bool on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
bool on_get_block_header_by_height(const COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::request& req, COMMAND_RPC_GET_BLOCK_HEADER_BY_HEIGHT::response& res, epee::json_rpc::error& error_resp, connection_context& cntx);
|
||||||
//-----------------------
|
//-----------------------
|
||||||
bool handle_command_line(const boost::program_options::variables_map& vm);
|
bool handle_command_line(const boost::program_options::variables_map& vm);
|
||||||
|
bool check_core_busy();
|
||||||
bool check_core_ready();
|
bool check_core_ready();
|
||||||
|
|
||||||
//utils
|
//utils
|
||||||
|
|
|
@ -214,6 +214,7 @@ namespace cryptonote
|
||||||
{
|
{
|
||||||
std::string status;
|
std::string status;
|
||||||
uint64_t height;
|
uint64_t height;
|
||||||
|
uint64_t target_height;
|
||||||
uint64_t difficulty;
|
uint64_t difficulty;
|
||||||
uint64_t tx_count;
|
uint64_t tx_count;
|
||||||
uint64_t tx_pool_size;
|
uint64_t tx_pool_size;
|
||||||
|
@ -226,6 +227,7 @@ namespace cryptonote
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
KV_SERIALIZE(status)
|
KV_SERIALIZE(status)
|
||||||
KV_SERIALIZE(height)
|
KV_SERIALIZE(height)
|
||||||
|
KV_SERIALIZE(target_height)
|
||||||
KV_SERIALIZE(difficulty)
|
KV_SERIALIZE(difficulty)
|
||||||
KV_SERIALIZE(tx_count)
|
KV_SERIALIZE(tx_count)
|
||||||
KV_SERIALIZE(tx_pool_size)
|
KV_SERIALIZE(tx_pool_size)
|
||||||
|
@ -260,6 +262,55 @@ namespace cryptonote
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------
|
||||||
|
struct COMMAND_RPC_MINING_STATUS
|
||||||
|
{
|
||||||
|
struct request
|
||||||
|
{
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct response
|
||||||
|
{
|
||||||
|
std::string status;
|
||||||
|
bool active;
|
||||||
|
uint64_t speed;
|
||||||
|
uint32_t threads_count;
|
||||||
|
std::string address;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(status)
|
||||||
|
KV_SERIALIZE(active)
|
||||||
|
KV_SERIALIZE(speed)
|
||||||
|
KV_SERIALIZE(threads_count)
|
||||||
|
KV_SERIALIZE(address)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
//-----------------------------------------------
|
||||||
|
struct COMMAND_RPC_SAVE_BC
|
||||||
|
{
|
||||||
|
struct request
|
||||||
|
{
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct response
|
||||||
|
{
|
||||||
|
std::string status;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(status)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
//
|
//
|
||||||
struct COMMAND_RPC_GETBLOCKCOUNT
|
struct COMMAND_RPC_GETBLOCKCOUNT
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#define CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB -6
|
#define CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB -6
|
||||||
#define CORE_RPC_ERROR_CODE_BLOCK_NOT_ACCEPTED -7
|
#define CORE_RPC_ERROR_CODE_BLOCK_NOT_ACCEPTED -7
|
||||||
#define CORE_RPC_ERROR_CODE_CORE_BUSY -9
|
#define CORE_RPC_ERROR_CODE_CORE_BUSY -9
|
||||||
|
#define CORE_RPC_ERROR_CODE_WRONG_BLOCKBLOB_SIZE -10
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
// Distributed under the MIT/X11 software license, see the accompanying
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "serialization.h"
|
#include "serialization.h"
|
||||||
#include "debug_archive.h"
|
#include "debug_archive.h"
|
||||||
#include "crypto/chacha8.h"
|
#include "crypto/chacha8.h"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <boost/type_traits/is_integral.hpp>
|
#include <boost/type_traits/is_integral.hpp>
|
||||||
|
#include <boost/type_traits/integral_constant.hpp>
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
struct is_blob_type { typedef boost::false_type type; };
|
struct is_blob_type { typedef boost::false_type type; };
|
||||||
|
@ -79,8 +80,10 @@ inline bool do_serialize(Archive &ar, T &v)
|
||||||
if (!r || !ar.stream().good()) return false; \
|
if (!r || !ar.stream().good()) return false; \
|
||||||
} while(0);
|
} while(0);
|
||||||
#define FIELDS(f) \
|
#define FIELDS(f) \
|
||||||
|
do { \
|
||||||
bool r = ::do_serialize(ar, f); \
|
bool r = ::do_serialize(ar, f); \
|
||||||
if (!r || !ar.stream().good()) return false;
|
if (!r || !ar.stream().good()) return false; \
|
||||||
|
} while(0);
|
||||||
#define FIELD(f) \
|
#define FIELD(f) \
|
||||||
do { \
|
do { \
|
||||||
ar.tag(#f); \
|
ar.tag(#f); \
|
||||||
|
@ -93,6 +96,12 @@ inline bool do_serialize(Archive &ar, T &v)
|
||||||
ar.serialize_varint(f); \
|
ar.serialize_varint(f); \
|
||||||
if (!ar.stream().good()) return false; \
|
if (!ar.stream().good()) return false; \
|
||||||
} while(0);
|
} while(0);
|
||||||
|
#define VARINT_FIELD_N(t, f) \
|
||||||
|
do { \
|
||||||
|
ar.tag(t); \
|
||||||
|
ar.serialize_varint(f); \
|
||||||
|
if (!ar.stream().good()) return false; \
|
||||||
|
} while(0);
|
||||||
|
|
||||||
namespace serialization {
|
namespace serialization {
|
||||||
namespace detail
|
namespace detail
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <iostream>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/program_options.hpp>
|
#include <boost/program_options.hpp>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
|
@ -17,6 +18,8 @@
|
||||||
#include "rpc/core_rpc_server_commands_defs.h"
|
#include "rpc/core_rpc_server_commands_defs.h"
|
||||||
#include "wallet/wallet_rpc_server.h"
|
#include "wallet/wallet_rpc_server.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
#include "crypto/crypto.h" // for crypto::secret_key definition
|
||||||
|
#include "crypto/electrum-words.h"
|
||||||
|
|
||||||
#if defined(WIN32)
|
#if defined(WIN32)
|
||||||
#include <crtdbg.h>
|
#include <crtdbg.h>
|
||||||
|
@ -38,6 +41,9 @@ namespace
|
||||||
const command_line::arg_descriptor<std::string> arg_daemon_address = {"daemon-address", "Use daemon instance at <host>:<port>", ""};
|
const command_line::arg_descriptor<std::string> arg_daemon_address = {"daemon-address", "Use daemon instance at <host>:<port>", ""};
|
||||||
const command_line::arg_descriptor<std::string> arg_daemon_host = {"daemon-host", "Use daemon instance at host <arg> instead of localhost", ""};
|
const command_line::arg_descriptor<std::string> arg_daemon_host = {"daemon-host", "Use daemon instance at host <arg> instead of localhost", ""};
|
||||||
const command_line::arg_descriptor<std::string> arg_password = {"password", "Wallet password", "", true};
|
const command_line::arg_descriptor<std::string> arg_password = {"password", "Wallet password", "", true};
|
||||||
|
const command_line::arg_descriptor<std::string> arg_electrum_seed = {"electrum-seed", "Specify electrum seed for wallet recovery/creation", ""};
|
||||||
|
const command_line::arg_descriptor<bool> arg_restore_deterministic_wallet = {"restore-deterministic-wallet", "Recover wallet using electrum-style mnemonic", false};
|
||||||
|
const command_line::arg_descriptor<bool> arg_non_deterministic = {"non-deterministic", "creates non-deterministic view and spend keys", false};
|
||||||
const command_line::arg_descriptor<int> arg_daemon_port = {"daemon-port", "Use daemon instance at port <arg> instead of 8081", 0};
|
const command_line::arg_descriptor<int> arg_daemon_port = {"daemon-port", "Use daemon instance at port <arg> instead of 8081", 0};
|
||||||
const command_line::arg_descriptor<uint32_t> arg_log_level = {"set_log", "", 0, true};
|
const command_line::arg_descriptor<uint32_t> arg_log_level = {"set_log", "", 0, true};
|
||||||
|
|
||||||
|
@ -64,19 +70,6 @@ namespace
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool parse_payment_id(const std::string& payment_id_str, crypto::hash& payment_id)
|
|
||||||
{
|
|
||||||
blobdata payment_id_data;
|
|
||||||
if(!string_tools::parse_hexstr_to_binbuff(payment_id_str, payment_id_data))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if(sizeof(crypto::hash) != payment_id_data.size())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
payment_id = *reinterpret_cast<const crypto::hash*>(payment_id_data.data());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
class message_writer
|
class message_writer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -181,6 +174,7 @@ simple_wallet::simple_wallet()
|
||||||
{
|
{
|
||||||
m_cmd_binder.set_handler("start_mining", boost::bind(&simple_wallet::start_mining, this, _1), "start_mining [<number_of_threads>] - Start mining in daemon");
|
m_cmd_binder.set_handler("start_mining", boost::bind(&simple_wallet::start_mining, this, _1), "start_mining [<number_of_threads>] - Start mining in daemon");
|
||||||
m_cmd_binder.set_handler("stop_mining", boost::bind(&simple_wallet::stop_mining, this, _1), "Stop mining in daemon");
|
m_cmd_binder.set_handler("stop_mining", boost::bind(&simple_wallet::stop_mining, this, _1), "Stop mining in daemon");
|
||||||
|
m_cmd_binder.set_handler("save_bc", boost::bind(&simple_wallet::save_bc, this, _1), "Save current blockchain data");
|
||||||
m_cmd_binder.set_handler("refresh", boost::bind(&simple_wallet::refresh, this, _1), "Resynchronize transactions and balance");
|
m_cmd_binder.set_handler("refresh", boost::bind(&simple_wallet::refresh, this, _1), "Resynchronize transactions and balance");
|
||||||
m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, _1), "Show current wallet balance");
|
m_cmd_binder.set_handler("balance", boost::bind(&simple_wallet::show_balance, this, _1), "Show current wallet balance");
|
||||||
m_cmd_binder.set_handler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, _1), "incoming_transfers [available|unavailable] - Show incoming transfers - all of them or filter them by availability");
|
m_cmd_binder.set_handler("incoming_transfers", boost::bind(&simple_wallet::show_incoming_transfers, this, _1), "incoming_transfers [available|unavailable] - Show incoming transfers - all of them or filter them by availability");
|
||||||
|
@ -201,7 +195,7 @@ bool simple_wallet::set_log(const std::vector<std::string> &args)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
uint16_t l = 0;
|
uint16_t l = 0;
|
||||||
if(!string_tools::get_xtype_from_string(l, args[0]))
|
if(!epee::string_tools::get_xtype_from_string(l, args[0]))
|
||||||
{
|
{
|
||||||
fail_msg_writer() << "wrong number format, use: set_log <log_level_number_0-4>";
|
fail_msg_writer() << "wrong number format, use: set_log <log_level_number_0-4>";
|
||||||
return true;
|
return true;
|
||||||
|
@ -220,16 +214,24 @@ bool simple_wallet::ask_wallet_create_if_needed()
|
||||||
{
|
{
|
||||||
std::string wallet_path;
|
std::string wallet_path;
|
||||||
|
|
||||||
std::cout << "Specify wallet file name (e.g., wallet.bin). If the wallet doesn't exist, it will be created.\n";
|
wallet_path = command_line::input_line(
|
||||||
std::cout << "Wallet file name: ";
|
"Specify wallet file name (e.g., wallet.bin). If the wallet doesn't exist, it will be created.\n"
|
||||||
|
"Wallet file name: "
|
||||||
std::getline(std::cin, wallet_path);
|
);
|
||||||
|
|
||||||
wallet_path = string_tools::trim(wallet_path);
|
|
||||||
|
|
||||||
bool keys_file_exists;
|
bool keys_file_exists;
|
||||||
bool wallet_file_exitst;
|
bool wallet_file_exists;
|
||||||
tools::wallet2::wallet_exists(wallet_path, keys_file_exists, wallet_file_exitst);
|
tools::wallet2::wallet_exists(wallet_path, keys_file_exists, wallet_file_exists);
|
||||||
|
|
||||||
|
// add logic to error out if new wallet requested but named wallet file exists
|
||||||
|
if (keys_file_exists || wallet_file_exists)
|
||||||
|
{
|
||||||
|
if (!m_generate_new.empty() || m_restore_deterministic_wallet)
|
||||||
|
{
|
||||||
|
fail_msg_writer() << "Attempting to generate or restore wallet, but specified file(s) exist. Exiting to not risk overwriting.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool r;
|
bool r;
|
||||||
if(keys_file_exists)
|
if(keys_file_exists)
|
||||||
|
@ -238,7 +240,7 @@ bool simple_wallet::ask_wallet_create_if_needed()
|
||||||
r = true;
|
r = true;
|
||||||
}else
|
}else
|
||||||
{
|
{
|
||||||
if(!wallet_file_exitst)
|
if(!wallet_file_exists)
|
||||||
{
|
{
|
||||||
std::cout << "The wallet doesn't exist, generating new one" << std::endl;
|
std::cout << "The wallet doesn't exist, generating new one" << std::endl;
|
||||||
m_generate_new = wallet_path;
|
m_generate_new = wallet_path;
|
||||||
|
@ -263,13 +265,14 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t c = 0;
|
if(!m_generate_new.empty() && !m_wallet_file.empty())
|
||||||
if(!m_generate_new.empty()) ++c;
|
|
||||||
if(!m_wallet_file.empty()) ++c;
|
|
||||||
if (1 != c)
|
|
||||||
{
|
{
|
||||||
if(!ask_wallet_create_if_needed())
|
fail_msg_writer() << "Specifying both --generate-new-wallet=\"wallet_name\" and --wallet-file=\"wallet_name\" doesn't make sense!";
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
else if (m_generate_new.empty() && m_wallet_file.empty())
|
||||||
|
{
|
||||||
|
if(!ask_wallet_create_if_needed()) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_daemon_host.empty())
|
if (m_daemon_host.empty())
|
||||||
|
@ -294,9 +297,36 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_generate_new.empty())
|
if (!m_generate_new.empty() || m_restore_deterministic_wallet)
|
||||||
{
|
{
|
||||||
bool r = new_wallet(m_generate_new, pwd_container.password());
|
if (m_wallet_file.empty()) m_wallet_file = m_generate_new; // alias for simplicity later
|
||||||
|
|
||||||
|
// check for recover flag. if present, require electrum word list (only recovery option for now).
|
||||||
|
if (m_restore_deterministic_wallet)
|
||||||
|
{
|
||||||
|
if (m_non_deterministic)
|
||||||
|
{
|
||||||
|
fail_msg_writer() << "Cannot specify both --restore-deterministic-wallet and --non-deterministic";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_electrum_seed.empty())
|
||||||
|
{
|
||||||
|
m_electrum_seed = command_line::input_line("Specify electrum seed: ");
|
||||||
|
if (m_electrum_seed.empty())
|
||||||
|
{
|
||||||
|
fail_msg_writer() << "specify a recovery parameter with the --electrum-seed=\"words list here\"";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!crypto::ElectrumWords::words_to_bytes(m_electrum_seed, m_recovery_key))
|
||||||
|
{
|
||||||
|
fail_msg_writer() << "electrum-style word list failed verification";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool r = new_wallet(m_wallet_file, pwd_container.password(), m_recovery_key, m_restore_deterministic_wallet, m_non_deterministic);
|
||||||
CHECK_AND_ASSERT_MES(r, false, "account creation failed");
|
CHECK_AND_ASSERT_MES(r, false, "account creation failed");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -318,11 +348,14 @@ bool simple_wallet::deinit()
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void simple_wallet::handle_command_line(const boost::program_options::variables_map& vm)
|
void simple_wallet::handle_command_line(const boost::program_options::variables_map& vm)
|
||||||
{
|
{
|
||||||
m_wallet_file = command_line::get_arg(vm, arg_wallet_file);
|
m_wallet_file = command_line::get_arg(vm, arg_wallet_file);
|
||||||
m_generate_new = command_line::get_arg(vm, arg_generate_new_wallet);
|
m_generate_new = command_line::get_arg(vm, arg_generate_new_wallet);
|
||||||
m_daemon_address = command_line::get_arg(vm, arg_daemon_address);
|
m_daemon_address = command_line::get_arg(vm, arg_daemon_address);
|
||||||
m_daemon_host = command_line::get_arg(vm, arg_daemon_host);
|
m_daemon_host = command_line::get_arg(vm, arg_daemon_host);
|
||||||
m_daemon_port = command_line::get_arg(vm, arg_daemon_port);
|
m_daemon_port = command_line::get_arg(vm, arg_daemon_port);
|
||||||
|
m_electrum_seed = command_line::get_arg(vm, arg_electrum_seed);
|
||||||
|
m_restore_deterministic_wallet = command_line::get_arg(vm, arg_restore_deterministic_wallet);
|
||||||
|
m_non_deterministic = command_line::get_arg(vm, arg_non_deterministic);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
bool simple_wallet::try_connect_to_daemon()
|
bool simple_wallet::try_connect_to_daemon()
|
||||||
|
@ -336,16 +369,19 @@ bool simple_wallet::try_connect_to_daemon()
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
bool simple_wallet::new_wallet(const string &wallet_file, const std::string& password)
|
bool simple_wallet::new_wallet(const string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key, bool recover, bool two_random)
|
||||||
{
|
{
|
||||||
m_wallet_file = wallet_file;
|
m_wallet_file = wallet_file;
|
||||||
|
|
||||||
m_wallet.reset(new tools::wallet2());
|
m_wallet.reset(new tools::wallet2());
|
||||||
m_wallet->callback(this);
|
m_wallet->callback(this);
|
||||||
|
|
||||||
|
crypto::secret_key recovery_val;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_wallet->generate(wallet_file, password);
|
recovery_val = m_wallet->generate(wallet_file, password, recovery_key, recover, two_random);
|
||||||
message_writer(epee::log_space::console_color_white, true) << "Generated new wallet: " << m_wallet->get_account().get_public_address_str() << std::endl << "view key: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key);
|
message_writer(epee::log_space::console_color_white, true) << "Generated new wallet: " << m_wallet->get_account().get_public_address_str() << std::endl << "view key: " << string_tools::pod_to_hex(m_wallet->get_account().get_keys().m_view_secret_key);
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
|
@ -356,6 +392,13 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
|
||||||
|
|
||||||
m_wallet->init(m_daemon_address);
|
m_wallet->init(m_daemon_address);
|
||||||
|
|
||||||
|
// convert rng value to electrum-style word list
|
||||||
|
std::string electrum_words;
|
||||||
|
crypto::ElectrumWords::bytes_to_words(recovery_val, electrum_words);
|
||||||
|
|
||||||
|
std::string print_electrum = "";
|
||||||
|
|
||||||
|
|
||||||
success_msg_writer() <<
|
success_msg_writer() <<
|
||||||
"**********************************************************************\n" <<
|
"**********************************************************************\n" <<
|
||||||
"Your wallet has been generated.\n" <<
|
"Your wallet has been generated.\n" <<
|
||||||
|
@ -363,8 +406,16 @@ bool simple_wallet::new_wallet(const string &wallet_file, const std::string& pas
|
||||||
"Use \"help\" command to see the list of available commands.\n" <<
|
"Use \"help\" command to see the list of available commands.\n" <<
|
||||||
"Always use \"exit\" command when closing simplewallet to save\n" <<
|
"Always use \"exit\" command when closing simplewallet to save\n" <<
|
||||||
"current session's state. Otherwise, you will possibly need to synchronize \n" <<
|
"current session's state. Otherwise, you will possibly need to synchronize \n" <<
|
||||||
"your wallet again. Your wallet key is NOT under risk anyway.\n" <<
|
"your wallet again. Your wallet key is NOT under risk anyway.\n"
|
||||||
"**********************************************************************";
|
;
|
||||||
|
|
||||||
|
if (!two_random)
|
||||||
|
{
|
||||||
|
success_msg_writer(true) << "\nPLEASE NOTE: the following 24 words can be used to recover access to your wallet. Please write them down and store them somewhere safe and secure. Please do not store them in your email or on file storage services outside of your immediate control. You will not be able to view these words again, so it is imperative to make note of them now.\n";
|
||||||
|
std::cout << electrum_words << std::endl;
|
||||||
|
}
|
||||||
|
success_msg_writer() << "**********************************************************************";
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
@ -491,6 +542,22 @@ bool simple_wallet::stop_mining(const std::vector<std::string>& args)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
bool simple_wallet::save_bc(const std::vector<std::string>& args)
|
||||||
|
{
|
||||||
|
if (!try_connect_to_daemon())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
COMMAND_RPC_SAVE_BC::request req;
|
||||||
|
COMMAND_RPC_SAVE_BC::response res;
|
||||||
|
bool r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/save_bc", req, res, m_http_client);
|
||||||
|
std::string err = interpret_rpc_response(r, res.status);
|
||||||
|
if (err.empty())
|
||||||
|
success_msg_writer() << "Blockchain saved";
|
||||||
|
else
|
||||||
|
fail_msg_writer() << "Blockchain can't be saved: " << err;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
void simple_wallet::on_new_block(uint64_t height, const cryptonote::block& block)
|
void simple_wallet::on_new_block(uint64_t height, const cryptonote::block& block)
|
||||||
{
|
{
|
||||||
m_refresh_progress_reporter.update(height, false);
|
m_refresh_progress_reporter.update(height, false);
|
||||||
|
@ -663,7 +730,7 @@ bool simple_wallet::show_payments(const std::vector<std::string> &args)
|
||||||
for(std::string arg : args)
|
for(std::string arg : args)
|
||||||
{
|
{
|
||||||
crypto::hash payment_id;
|
crypto::hash payment_id;
|
||||||
if(parse_payment_id(arg, payment_id))
|
if(tools::wallet2::parse_payment_id(arg, payment_id))
|
||||||
{
|
{
|
||||||
std::list<tools::wallet2::payment_details> payments;
|
std::list<tools::wallet2::payment_details> payments;
|
||||||
m_wallet->get_payments(payment_id, payments);
|
m_wallet->get_payments(payment_id, payments);
|
||||||
|
@ -732,7 +799,7 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t fake_outs_count;
|
size_t fake_outs_count;
|
||||||
if(!string_tools::get_xtype_from_string(fake_outs_count, local_args[0]))
|
if(!epee::string_tools::get_xtype_from_string(fake_outs_count, local_args[0]))
|
||||||
{
|
{
|
||||||
fail_msg_writer() << "mixin_count should be non-negative integer, got " << local_args[0];
|
fail_msg_writer() << "mixin_count should be non-negative integer, got " << local_args[0];
|
||||||
return true;
|
return true;
|
||||||
|
@ -746,7 +813,7 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
|
||||||
local_args.pop_back();
|
local_args.pop_back();
|
||||||
|
|
||||||
crypto::hash payment_id;
|
crypto::hash payment_id;
|
||||||
bool r = parse_payment_id(payment_id_str, payment_id);
|
bool r = tools::wallet2::parse_payment_id(payment_id_str, payment_id);
|
||||||
if(r)
|
if(r)
|
||||||
{
|
{
|
||||||
std::string extra_nonce;
|
std::string extra_nonce;
|
||||||
|
@ -912,6 +979,9 @@ int main(int argc, char* argv[])
|
||||||
command_line::add_arg(desc_params, arg_daemon_port);
|
command_line::add_arg(desc_params, arg_daemon_port);
|
||||||
command_line::add_arg(desc_params, arg_command);
|
command_line::add_arg(desc_params, arg_command);
|
||||||
command_line::add_arg(desc_params, arg_log_level);
|
command_line::add_arg(desc_params, arg_log_level);
|
||||||
|
command_line::add_arg(desc_params, arg_restore_deterministic_wallet );
|
||||||
|
command_line::add_arg(desc_params, arg_non_deterministic );
|
||||||
|
command_line::add_arg(desc_params, arg_electrum_seed );
|
||||||
tools::wallet_rpc_server::init_options(desc_params);
|
tools::wallet_rpc_server::init_options(desc_params);
|
||||||
|
|
||||||
po::positional_options_description positional_options;
|
po::positional_options_description positional_options;
|
||||||
|
@ -927,7 +997,7 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
if (command_line::get_arg(vm, command_line::arg_help))
|
if (command_line::get_arg(vm, command_line::arg_help))
|
||||||
{
|
{
|
||||||
success_msg_writer() << "bytecoin wallet v" << PROJECT_VERSION_LONG;
|
success_msg_writer() << CRYPTONOTE_NAME << " wallet v" << PROJECT_VERSION_LONG;
|
||||||
success_msg_writer() << "Usage: simplewallet [--wallet-file=<file>|--generate-new-wallet=<file>] [--daemon-address=<host>:<port>] [<COMMAND>]";
|
success_msg_writer() << "Usage: simplewallet [--wallet-file=<file>|--generate-new-wallet=<file>] [--daemon-address=<host>:<port>] [<COMMAND>]";
|
||||||
success_msg_writer() << desc_all << '\n' << w.get_commands_str();
|
success_msg_writer() << desc_all << '\n' << w.get_commands_str();
|
||||||
return false;
|
return false;
|
||||||
|
@ -944,7 +1014,7 @@ int main(int argc, char* argv[])
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
if (!r)
|
if (!r)
|
||||||
return 1;
|
return 0;
|
||||||
|
|
||||||
//set up logging options
|
//set up logging options
|
||||||
log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2);
|
log_space::get_set_log_detalisation_level(true, LOG_LEVEL_2);
|
||||||
|
@ -1037,15 +1107,21 @@ int main(int argc, char* argv[])
|
||||||
|
|
||||||
std::vector<std::string> command = command_line::get_arg(vm, arg_command);
|
std::vector<std::string> command = command_line::get_arg(vm, arg_command);
|
||||||
if (!command.empty())
|
if (!command.empty())
|
||||||
|
{
|
||||||
w.process_command(command);
|
w.process_command(command);
|
||||||
|
|
||||||
tools::signal_handler::install([&w] {
|
|
||||||
w.stop();
|
w.stop();
|
||||||
});
|
w.deinit();
|
||||||
w.run();
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tools::signal_handler::install([&w] {
|
||||||
|
w.stop();
|
||||||
|
});
|
||||||
|
w.run();
|
||||||
|
|
||||||
w.deinit();
|
w.deinit();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 0;
|
||||||
//CATCH_ENTRY_L0("main", 1);
|
//CATCH_ENTRY_L0("main", 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "wallet/wallet2.h"
|
#include "wallet/wallet2.h"
|
||||||
#include "console_handler.h"
|
#include "console_handler.h"
|
||||||
#include "password_container.h"
|
#include "password_container.h"
|
||||||
|
#include "crypto/crypto.h" // for definition of crypto::secret_key
|
||||||
|
|
||||||
|
|
||||||
namespace cryptonote
|
namespace cryptonote
|
||||||
|
@ -39,13 +40,14 @@ namespace cryptonote
|
||||||
|
|
||||||
bool run_console_handler();
|
bool run_console_handler();
|
||||||
|
|
||||||
bool new_wallet(const std::string &wallet_file, const std::string& password);
|
bool new_wallet(const std::string &wallet_file, const std::string& password, const crypto::secret_key& recovery_key = crypto::secret_key(), bool recover = false, bool two_random = false);
|
||||||
bool open_wallet(const std::string &wallet_file, const std::string& password);
|
bool open_wallet(const std::string &wallet_file, const std::string& password);
|
||||||
bool close_wallet();
|
bool close_wallet();
|
||||||
|
|
||||||
bool help(const std::vector<std::string> &args = std::vector<std::string>());
|
bool help(const std::vector<std::string> &args = std::vector<std::string>());
|
||||||
bool start_mining(const std::vector<std::string> &args);
|
bool start_mining(const std::vector<std::string> &args);
|
||||||
bool stop_mining(const std::vector<std::string> &args);
|
bool stop_mining(const std::vector<std::string> &args);
|
||||||
|
bool save_bc(const std::vector<std::string>& args);
|
||||||
bool refresh(const std::vector<std::string> &args);
|
bool refresh(const std::vector<std::string> &args);
|
||||||
bool show_balance(const std::vector<std::string> &args = std::vector<std::string>());
|
bool show_balance(const std::vector<std::string> &args = std::vector<std::string>());
|
||||||
bool show_incoming_transfers(const std::vector<std::string> &args);
|
bool show_incoming_transfers(const std::vector<std::string> &args);
|
||||||
|
@ -124,6 +126,12 @@ namespace cryptonote
|
||||||
std::string m_generate_new;
|
std::string m_generate_new;
|
||||||
std::string m_import_path;
|
std::string m_import_path;
|
||||||
|
|
||||||
|
std::string m_electrum_seed; // electrum-style seed parameter
|
||||||
|
|
||||||
|
crypto::secret_key m_recovery_key; // recovery key (used as random for wallet gen)
|
||||||
|
bool m_restore_deterministic_wallet; // recover flag
|
||||||
|
bool m_non_deterministic; // old 2-random generation
|
||||||
|
|
||||||
std::string m_daemon_address;
|
std::string m_daemon_address;
|
||||||
std::string m_daemon_host;
|
std::string m_daemon_host;
|
||||||
int m_daemon_port;
|
int m_daemon_port;
|
||||||
|
@ -131,7 +139,7 @@ namespace cryptonote
|
||||||
epee::console_handlers_binder m_cmd_binder;
|
epee::console_handlers_binder m_cmd_binder;
|
||||||
|
|
||||||
std::unique_ptr<tools::wallet2> m_wallet;
|
std::unique_ptr<tools::wallet2> m_wallet;
|
||||||
net_utils::http::http_simple_client m_http_client;
|
epee::net_utils::http::http_simple_client m_http_client;
|
||||||
refresh_progress_reporter_t m_refresh_progress_reporter;
|
refresh_progress_reporter_t m_refresh_progress_reporter;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#define BUILD_COMMIT_ID "@VERSION@"
|
#define BUILD_COMMIT_ID "@VERSION@"
|
||||||
#define PROJECT_VERSION "0.8.6"
|
#define PROJECT_VERSION "0.8.8"
|
||||||
#define PROJECT_VERSION_BUILD_NO "295"
|
#define PROJECT_VERSION_BUILD_NO "1"
|
||||||
#define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO "(" BUILD_COMMIT_ID ")"
|
#define PROJECT_VERSION_LONG PROJECT_VERSION "." PROJECT_VERSION_BUILD_NO "(" BUILD_COMMIT_ID ")"
|
||||||
|
|
|
@ -19,6 +19,7 @@ using namespace epee;
|
||||||
#include "profile_tools.h"
|
#include "profile_tools.h"
|
||||||
#include "crypto/crypto.h"
|
#include "crypto/crypto.h"
|
||||||
#include "serialization/binary_utils.h"
|
#include "serialization/binary_utils.h"
|
||||||
|
#include "cryptonote_protocol/blobdatatype.h"
|
||||||
|
|
||||||
using namespace cryptonote;
|
using namespace cryptonote;
|
||||||
|
|
||||||
|
@ -37,6 +38,7 @@ void do_prepare_file_names(const std::string& file_path, std::string& keys_file,
|
||||||
keys_file += ".keys";
|
keys_file += ".keys";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} //namespace
|
} //namespace
|
||||||
|
|
||||||
namespace tools
|
namespace tools
|
||||||
|
@ -434,7 +436,7 @@ void wallet2::load_keys(const std::string& keys_file_name, const std::string& pa
|
||||||
THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password);
|
THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password);
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::generate(const std::string& wallet_, const std::string& password)
|
crypto::secret_key wallet2::generate(const std::string& wallet_, const std::string& password, const crypto::secret_key& recovery_param, bool recover, bool two_random)
|
||||||
{
|
{
|
||||||
clear();
|
clear();
|
||||||
prepare_file_names(wallet_);
|
prepare_file_names(wallet_);
|
||||||
|
@ -443,7 +445,8 @@ void wallet2::generate(const std::string& wallet_, const std::string& password)
|
||||||
THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file);
|
THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_exists, m_wallet_file);
|
||||||
THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file);
|
THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(m_keys_file, ignored_ec), error::file_exists, m_keys_file);
|
||||||
|
|
||||||
m_account.generate();
|
crypto::secret_key retval = m_account.generate(recovery_param, recover, two_random);
|
||||||
|
|
||||||
m_account_public_address = m_account.get_keys().m_account_address;
|
m_account_public_address = m_account.get_keys().m_account_address;
|
||||||
|
|
||||||
bool r = store_keys(m_keys_file, password);
|
bool r = store_keys(m_keys_file, password);
|
||||||
|
@ -453,16 +456,30 @@ void wallet2::generate(const std::string& wallet_, const std::string& password)
|
||||||
if(!r) LOG_PRINT_RED_L0("String with address text not saved");
|
if(!r) LOG_PRINT_RED_L0("String with address text not saved");
|
||||||
|
|
||||||
store();
|
store();
|
||||||
|
return retval;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
void wallet2::wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exitst)
|
void wallet2::wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exists)
|
||||||
{
|
{
|
||||||
std::string keys_file, wallet_file;
|
std::string keys_file, wallet_file;
|
||||||
do_prepare_file_names(file_path, keys_file, wallet_file);
|
do_prepare_file_names(file_path, keys_file, wallet_file);
|
||||||
|
|
||||||
boost::system::error_code ignore;
|
boost::system::error_code ignore;
|
||||||
keys_file_exists = boost::filesystem::exists(keys_file, ignore);
|
keys_file_exists = boost::filesystem::exists(keys_file, ignore);
|
||||||
wallet_file_exitst = boost::filesystem::exists(wallet_file, ignore);
|
wallet_file_exists = boost::filesystem::exists(wallet_file, ignore);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
bool wallet2::parse_payment_id(const std::string& payment_id_str, crypto::hash& payment_id)
|
||||||
|
{
|
||||||
|
cryptonote::blobdata payment_id_data;
|
||||||
|
if(!epee::string_tools::parse_hexstr_to_binbuff(payment_id_str, payment_id_data))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if(sizeof(crypto::hash) != payment_id_data.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
payment_id = *reinterpret_cast<const crypto::hash*>(payment_id_data.data());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
bool wallet2::prepare_file_names(const std::string& file_path)
|
bool wallet2::prepare_file_names(const std::string& file_path)
|
||||||
|
|
|
@ -97,12 +97,17 @@ namespace tools
|
||||||
END_SERIALIZE()
|
END_SERIALIZE()
|
||||||
};
|
};
|
||||||
|
|
||||||
void generate(const std::string& wallet, const std::string& password);
|
crypto::secret_key generate(const std::string& wallet, const std::string& password, const crypto::secret_key& recovery_param = crypto::secret_key(), bool recover = false, bool two_random = false);
|
||||||
void load(const std::string& wallet, const std::string& password);
|
void load(const std::string& wallet, const std::string& password);
|
||||||
void store();
|
void store();
|
||||||
cryptonote::account_base& get_account(){return m_account;}
|
cryptonote::account_base& get_account(){return m_account;}
|
||||||
|
|
||||||
void init(const std::string& daemon_address = "http://localhost:8080", uint64_t upper_transaction_size_limit = CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE*2 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE);
|
// upper_transaction_size_limit as defined below is set to
|
||||||
|
// approximately 125% of the fixed minimum allowable penalty
|
||||||
|
// free block size. TODO: fix this so that it actually takes
|
||||||
|
// into account the current median block size rather than
|
||||||
|
// the minimum block size.
|
||||||
|
void init(const std::string& daemon_address = "http://localhost:8080", uint64_t upper_transaction_size_limit = ((CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE);
|
||||||
bool deinit();
|
bool deinit();
|
||||||
|
|
||||||
void stop() { m_run.store(false, std::memory_order_relaxed); }
|
void stop() { m_run.store(false, std::memory_order_relaxed); }
|
||||||
|
@ -144,7 +149,9 @@ namespace tools
|
||||||
a & m_payments;
|
a & m_payments;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exitst);
|
static void wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exists);
|
||||||
|
|
||||||
|
static bool parse_payment_id(const std::string& payment_id_str, crypto::hash& payment_id);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool store_keys(const std::string& keys_file_name, const std::string& password);
|
bool store_keys(const std::string& keys_file_name, const std::string& password);
|
||||||
|
@ -220,6 +227,7 @@ namespace boost
|
||||||
|
|
||||||
namespace tools
|
namespace tools
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
@ -326,7 +334,7 @@ namespace tools
|
||||||
req.amounts.push_back(it->amount());
|
req.amounts.push_back(it->amount());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool r = net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/getrandom_outs.bin", req, daemon_resp, m_http_client, 200000);
|
bool r = epee::net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/getrandom_outs.bin", req, daemon_resp, m_http_client, 200000);
|
||||||
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "getrandom_outs.bin");
|
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "getrandom_outs.bin");
|
||||||
THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "getrandom_outs.bin");
|
THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "getrandom_outs.bin");
|
||||||
THROW_WALLET_EXCEPTION_IF(daemon_resp.status != CORE_RPC_STATUS_OK, error::get_random_outs_error, daemon_resp.status);
|
THROW_WALLET_EXCEPTION_IF(daemon_resp.status != CORE_RPC_STATUS_OK, error::get_random_outs_error, daemon_resp.status);
|
||||||
|
@ -421,7 +429,7 @@ namespace tools
|
||||||
COMMAND_RPC_SEND_RAW_TX::request req;
|
COMMAND_RPC_SEND_RAW_TX::request req;
|
||||||
req.tx_as_hex = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(tx));
|
req.tx_as_hex = epee::string_tools::buff_to_hex_nodelimer(tx_to_blob(tx));
|
||||||
COMMAND_RPC_SEND_RAW_TX::response daemon_send_resp;
|
COMMAND_RPC_SEND_RAW_TX::response daemon_send_resp;
|
||||||
r = net_utils::invoke_http_json_remote_command2(m_daemon_address + "/sendrawtransaction", req, daemon_send_resp, m_http_client, 200000);
|
r = epee::net_utils::invoke_http_json_remote_command2(m_daemon_address + "/sendrawtransaction", req, daemon_send_resp, m_http_client, 200000);
|
||||||
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "sendrawtransaction");
|
THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "sendrawtransaction");
|
||||||
THROW_WALLET_EXCEPTION_IF(daemon_send_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "sendrawtransaction");
|
THROW_WALLET_EXCEPTION_IF(daemon_send_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "sendrawtransaction");
|
||||||
THROW_WALLET_EXCEPTION_IF(daemon_send_resp.status != CORE_RPC_STATUS_OK, error::tx_rejected, tx, daemon_send_resp.status);
|
THROW_WALLET_EXCEPTION_IF(daemon_send_resp.status != CORE_RPC_STATUS_OK, error::tx_rejected, tx, daemon_send_resp.status);
|
||||||
|
|
|
@ -188,6 +188,17 @@ namespace tools
|
||||||
|
|
||||||
std::string to_string() const { return wallet_logic_error::to_string(); }
|
std::string to_string() const { return wallet_logic_error::to_string(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------------------------------------
|
||||||
|
struct invalid_pregenerated_random : public wallet_logic_error
|
||||||
|
{
|
||||||
|
explicit invalid_pregenerated_random (std::string&& loc)
|
||||||
|
: wallet_logic_error(std::move(loc), "invalid pregenerated random for wallet creation/recovery")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string to_string() const { return wallet_logic_error::to_string(); }
|
||||||
|
};
|
||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
struct refresh_error : public wallet_logic_error
|
struct refresh_error : public wallet_logic_error
|
||||||
{
|
{
|
||||||
|
|
|
@ -71,6 +71,21 @@ namespace tools
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
bool wallet_rpc_server::on_getaddress(const wallet_rpc::COMMAND_RPC_GET_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_GET_ADDRESS::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
res.address = m_wallet.get_account().get_public_address_str();
|
||||||
|
}
|
||||||
|
catch (std::exception& e)
|
||||||
|
{
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||||
|
er.message = e.what();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
bool wallet_rpc_server::on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
bool wallet_rpc_server::on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -87,10 +102,37 @@ namespace tools
|
||||||
de.amount = it->amount;
|
de.amount = it->amount;
|
||||||
dsts.push_back(de);
|
dsts.push_back(de);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> extra;
|
||||||
|
if (!req.payment_id.empty()) {
|
||||||
|
|
||||||
|
/* Just to clarify */
|
||||||
|
const std::string& payment_id_str = req.payment_id;
|
||||||
|
|
||||||
|
crypto::hash payment_id;
|
||||||
|
/* Parse payment ID */
|
||||||
|
if (!wallet2::parse_payment_id(payment_id_str, payment_id)) {
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID;
|
||||||
|
er.message = "Payment id has invalid format: \"" + payment_id_str + "\", expected 64-character string";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string extra_nonce;
|
||||||
|
cryptonote::set_payment_id_to_tx_extra_nonce(extra_nonce, payment_id);
|
||||||
|
|
||||||
|
/* Append Payment ID data into extra */
|
||||||
|
if (!cryptonote::add_extra_nonce_to_tx_extra(extra, extra_nonce)) {
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID;
|
||||||
|
er.message = "Something went wront with payment_id. Please check its format: \"" + payment_id_str + "\", expected 64-character string";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
cryptonote::transaction tx;
|
cryptonote::transaction tx;
|
||||||
m_wallet.transfer(dsts, req.mixin, req.unlock_time, req.fee, std::vector<uint8_t>(), tx);
|
m_wallet.transfer(dsts, req.mixin, req.unlock_time, req.fee, extra, tx);
|
||||||
res.tx_hash = boost::lexical_cast<std::string>(cryptonote::get_transaction_hash(tx));
|
res.tx_hash = boost::lexical_cast<std::string>(cryptonote::get_transaction_hash(tx));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -166,4 +208,55 @@ namespace tools
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//------------------------------------------------------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
|
bool wallet_rpc_server::on_incoming_transfers(const wallet_rpc::COMMAND_RPC_INCOMING_TRANSFERS::request& req, wallet_rpc::COMMAND_RPC_INCOMING_TRANSFERS::response& res, epee::json_rpc::error& er, connection_context& cntx)
|
||||||
|
{
|
||||||
|
if(req.transfer_type.compare("all") != 0 && req.transfer_type.compare("available") != 0 && req.transfer_type.compare("unavailable") != 0)
|
||||||
|
{
|
||||||
|
er.code = WALLET_RPC_ERROR_CODE_TRANSFER_TYPE;
|
||||||
|
er.message = "Transfer type must be one of: all, available, or unavailable";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool filter = false;
|
||||||
|
bool available = false;
|
||||||
|
if (req.transfer_type.compare("available") == 0)
|
||||||
|
{
|
||||||
|
filter = true;
|
||||||
|
available = true;
|
||||||
|
}
|
||||||
|
else if (req.transfer_type.compare("unavailable") == 0)
|
||||||
|
{
|
||||||
|
filter = true;
|
||||||
|
available = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
wallet2::transfer_container transfers;
|
||||||
|
m_wallet.get_transfers(transfers);
|
||||||
|
|
||||||
|
bool transfers_found = false;
|
||||||
|
for (const auto& td : transfers)
|
||||||
|
{
|
||||||
|
if (!filter || available != td.m_spent)
|
||||||
|
{
|
||||||
|
if (!transfers_found)
|
||||||
|
{
|
||||||
|
transfers_found = true;
|
||||||
|
}
|
||||||
|
wallet_rpc::transfer_details rpc_transfers;
|
||||||
|
rpc_transfers.amount = td.amount();
|
||||||
|
rpc_transfers.spent = td.m_spent;
|
||||||
|
rpc_transfers.global_index = td.m_global_output_index;
|
||||||
|
rpc_transfers.tx_hash = boost::lexical_cast<std::string>(cryptonote::get_transaction_hash(td.m_tx));
|
||||||
|
res.transfers.push_back(rpc_transfers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!transfers_found)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//------------------------------------------------------------------------------------------------------------------------------
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,18 +35,22 @@ namespace tools
|
||||||
|
|
||||||
BEGIN_URI_MAP2()
|
BEGIN_URI_MAP2()
|
||||||
BEGIN_JSON_RPC_MAP("/json_rpc")
|
BEGIN_JSON_RPC_MAP("/json_rpc")
|
||||||
MAP_JON_RPC_WE("getbalance", on_getbalance, wallet_rpc::COMMAND_RPC_GET_BALANCE)
|
MAP_JON_RPC_WE("getbalance", on_getbalance, wallet_rpc::COMMAND_RPC_GET_BALANCE)
|
||||||
MAP_JON_RPC_WE("transfer", on_transfer, wallet_rpc::COMMAND_RPC_TRANSFER)
|
MAP_JON_RPC_WE("getaddress", on_getaddress, wallet_rpc::COMMAND_RPC_GET_ADDRESS)
|
||||||
MAP_JON_RPC_WE("store", on_store, wallet_rpc::COMMAND_RPC_STORE)
|
MAP_JON_RPC_WE("transfer", on_transfer, wallet_rpc::COMMAND_RPC_TRANSFER)
|
||||||
MAP_JON_RPC_WE("get_payments", on_get_payments, wallet_rpc::COMMAND_RPC_GET_PAYMENTS)
|
MAP_JON_RPC_WE("store", on_store, wallet_rpc::COMMAND_RPC_STORE)
|
||||||
|
MAP_JON_RPC_WE("get_payments", on_get_payments, wallet_rpc::COMMAND_RPC_GET_PAYMENTS)
|
||||||
|
MAP_JON_RPC_WE("incoming_transfers", on_incoming_transfers, wallet_rpc::COMMAND_RPC_INCOMING_TRANSFERS)
|
||||||
END_JSON_RPC_MAP()
|
END_JSON_RPC_MAP()
|
||||||
END_URI_MAP2()
|
END_URI_MAP2()
|
||||||
|
|
||||||
//json_rpc
|
//json_rpc
|
||||||
bool on_getbalance(const wallet_rpc::COMMAND_RPC_GET_BALANCE::request& req, wallet_rpc::COMMAND_RPC_GET_BALANCE::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
bool on_getbalance(const wallet_rpc::COMMAND_RPC_GET_BALANCE::request& req, wallet_rpc::COMMAND_RPC_GET_BALANCE::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||||
|
bool on_getaddress(const wallet_rpc::COMMAND_RPC_GET_ADDRESS::request& req, wallet_rpc::COMMAND_RPC_GET_ADDRESS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||||
bool on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
bool on_transfer(const wallet_rpc::COMMAND_RPC_TRANSFER::request& req, wallet_rpc::COMMAND_RPC_TRANSFER::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||||
bool on_store(const wallet_rpc::COMMAND_RPC_STORE::request& req, wallet_rpc::COMMAND_RPC_STORE::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
bool on_store(const wallet_rpc::COMMAND_RPC_STORE::request& req, wallet_rpc::COMMAND_RPC_STORE::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||||
bool on_get_payments(const wallet_rpc::COMMAND_RPC_GET_PAYMENTS::request& req, wallet_rpc::COMMAND_RPC_GET_PAYMENTS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
bool on_get_payments(const wallet_rpc::COMMAND_RPC_GET_PAYMENTS::request& req, wallet_rpc::COMMAND_RPC_GET_PAYMENTS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||||
|
bool on_incoming_transfers(const wallet_rpc::COMMAND_RPC_INCOMING_TRANSFERS::request& req, wallet_rpc::COMMAND_RPC_INCOMING_TRANSFERS::response& res, epee::json_rpc::error& er, connection_context& cntx);
|
||||||
|
|
||||||
bool handle_command_line(const boost::program_options::variables_map& vm);
|
bool handle_command_line(const boost::program_options::variables_map& vm);
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,24 @@ namespace wallet_rpc
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct COMMAND_RPC_GET_ADDRESS
|
||||||
|
{
|
||||||
|
struct request
|
||||||
|
{
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct response
|
||||||
|
{
|
||||||
|
std::string address;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(address)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct trnsfer_destination
|
struct trnsfer_destination
|
||||||
{
|
{
|
||||||
uint64_t amount;
|
uint64_t amount;
|
||||||
|
@ -52,12 +70,14 @@ namespace wallet_rpc
|
||||||
uint64_t fee;
|
uint64_t fee;
|
||||||
uint64_t mixin;
|
uint64_t mixin;
|
||||||
uint64_t unlock_time;
|
uint64_t unlock_time;
|
||||||
|
std::string payment_id;
|
||||||
|
|
||||||
BEGIN_KV_SERIALIZE_MAP()
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
KV_SERIALIZE(destinations)
|
KV_SERIALIZE(destinations)
|
||||||
KV_SERIALIZE(fee)
|
KV_SERIALIZE(fee)
|
||||||
KV_SERIALIZE(mixin)
|
KV_SERIALIZE(mixin)
|
||||||
KV_SERIALIZE(unlock_time)
|
KV_SERIALIZE(unlock_time)
|
||||||
|
KV_SERIALIZE(payment_id)
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -121,6 +141,42 @@ namespace wallet_rpc
|
||||||
END_KV_SERIALIZE_MAP()
|
END_KV_SERIALIZE_MAP()
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct transfer_details
|
||||||
|
{
|
||||||
|
uint64_t amount;
|
||||||
|
bool spent;
|
||||||
|
uint64_t global_index;
|
||||||
|
std::string tx_hash;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(amount)
|
||||||
|
KV_SERIALIZE(spent)
|
||||||
|
KV_SERIALIZE(global_index)
|
||||||
|
KV_SERIALIZE(tx_hash)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct COMMAND_RPC_INCOMING_TRANSFERS
|
||||||
|
{
|
||||||
|
struct request
|
||||||
|
{
|
||||||
|
std::string transfer_type;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(transfer_type)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
|
||||||
|
struct response
|
||||||
|
{
|
||||||
|
std::list<transfer_details> transfers;
|
||||||
|
|
||||||
|
BEGIN_KV_SERIALIZE_MAP()
|
||||||
|
KV_SERIALIZE(transfers)
|
||||||
|
END_KV_SERIALIZE_MAP()
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,3 +10,4 @@
|
||||||
#define WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY -3
|
#define WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY -3
|
||||||
#define WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR -4
|
#define WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR -4
|
||||||
#define WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID -5
|
#define WALLET_RPC_ERROR_CODE_WRONG_PAYMENT_ID -5
|
||||||
|
#define WALLET_RPC_ERROR_CODE_TRANSFER_TYPE -6
|
||||||
|
|
|
@ -31,16 +31,16 @@ add_executable(unit_tests ${UNIT_TESTS})
|
||||||
add_executable(net_load_tests_clt net_load_tests/clt.cpp)
|
add_executable(net_load_tests_clt net_load_tests/clt.cpp)
|
||||||
add_executable(net_load_tests_srv net_load_tests/srv.cpp)
|
add_executable(net_load_tests_srv net_load_tests/srv.cpp)
|
||||||
|
|
||||||
target_link_libraries(core_proxy cryptonote_core common crypto upnpc-static ${Boost_LIBRARIES})
|
target_link_libraries(core_proxy cryptonote_core common crypto upnpc-static ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||||
target_link_libraries(coretests cryptonote_core common crypto ${Boost_LIBRARIES})
|
target_link_libraries(coretests cryptonote_core common crypto ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||||
target_link_libraries(difficulty-tests cryptonote_core)
|
target_link_libraries(difficulty-tests cryptonote_core)
|
||||||
target_link_libraries(functional_tests cryptonote_core wallet common crypto ${Boost_LIBRARIES})
|
target_link_libraries(functional_tests cryptonote_core wallet common crypto ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||||
target_link_libraries(hash-tests crypto)
|
target_link_libraries(hash-tests crypto)
|
||||||
target_link_libraries(hash-target-tests crypto cryptonote_core)
|
target_link_libraries(hash-target-tests crypto cryptonote_core)
|
||||||
target_link_libraries(performance_tests cryptonote_core common crypto ${Boost_LIBRARIES})
|
target_link_libraries(performance_tests cryptonote_core common crypto ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||||
target_link_libraries(unit_tests cryptonote_core common crypto gtest_main ${Boost_LIBRARIES})
|
target_link_libraries(unit_tests cryptonote_core common crypto gtest_main ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||||
target_link_libraries(net_load_tests_clt cryptonote_core common crypto gtest_main ${Boost_LIBRARIES})
|
target_link_libraries(net_load_tests_clt cryptonote_core common crypto gtest_main ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||||
target_link_libraries(net_load_tests_srv cryptonote_core common crypto gtest_main ${Boost_LIBRARIES})
|
target_link_libraries(net_load_tests_srv cryptonote_core common crypto gtest_main ${CMAKE_THREAD_LIBS_INIT} ${Boost_LIBRARIES})
|
||||||
|
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
set_property(TARGET gtest gtest_main unit_tests net_load_tests_clt net_load_tests_srv APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-undef -Wno-sign-compare")
|
set_property(TARGET gtest gtest_main unit_tests net_load_tests_clt net_load_tests_srv APPEND_STRING PROPERTY COMPILE_FLAGS " -Wno-undef -Wno-sign-compare")
|
||||||
|
|
|
@ -41,6 +41,7 @@ namespace tests
|
||||||
public:
|
public:
|
||||||
void on_synchronized(){}
|
void on_synchronized(){}
|
||||||
uint64_t get_current_blockchain_height(){return 1;}
|
uint64_t get_current_blockchain_height(){return 1;}
|
||||||
|
void set_target_blockchain_height(uint64_t) {}
|
||||||
bool init(const boost::program_options::variables_map& vm);
|
bool init(const boost::program_options::variables_map& vm);
|
||||||
bool deinit(){return true;}
|
bool deinit(){return true;}
|
||||||
bool get_short_chain_history(std::list<crypto::hash>& ids);
|
bool get_short_chain_history(std::list<crypto::hash>& ids);
|
||||||
|
|
|
@ -21,15 +21,15 @@ namespace
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
TRY_ENTRY();
|
TRY_ENTRY();
|
||||||
string_tools::set_module_name_and_folder(argv[0]);
|
epee::string_tools::set_module_name_and_folder(argv[0]);
|
||||||
|
|
||||||
//set up logging options
|
//set up logging options
|
||||||
log_space::get_set_log_detalisation_level(true, LOG_LEVEL_3);
|
epee::log_space::get_set_log_detalisation_level(true, LOG_LEVEL_3);
|
||||||
log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL, LOG_LEVEL_2);
|
epee::log_space::log_singletone::add_logger(LOGGER_CONSOLE, NULL, NULL, LOG_LEVEL_2);
|
||||||
|
|
||||||
log_space::log_singletone::add_logger(LOGGER_FILE,
|
epee::log_space::log_singletone::add_logger(LOGGER_FILE,
|
||||||
log_space::log_singletone::get_default_log_file().c_str(),
|
epee::log_space::log_singletone::get_default_log_file().c_str(),
|
||||||
log_space::log_singletone::get_default_log_folder().c_str());
|
epee::log_space::log_singletone::get_default_log_folder().c_str());
|
||||||
|
|
||||||
po::options_description desc_options("Allowed options");
|
po::options_description desc_options("Allowed options");
|
||||||
command_line::add_arg(desc_options, command_line::arg_help);
|
command_line::add_arg(desc_options, command_line::arg_help);
|
||||||
|
|
|
@ -0,0 +1,45 @@
|
||||||
|
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "crypto/crypto.h"
|
||||||
|
#include "cryptonote_core/cryptonote_basic.h"
|
||||||
|
|
||||||
|
class test_cn_slow_hash
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static const size_t loop_count = 10;
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct data_t
|
||||||
|
{
|
||||||
|
char data[13];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
static_assert(13 == sizeof(data_t), "Invalid structure size");
|
||||||
|
|
||||||
|
bool init()
|
||||||
|
{
|
||||||
|
if (!epee::string_tools::hex_to_pod("63617665617420656d70746f72", m_data))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!epee::string_tools::hex_to_pod("bbec2cacf69866a8e740380fe7b818fc78f8571221742d729d9d02d7f8989b87", m_expected_hash))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool test()
|
||||||
|
{
|
||||||
|
crypto::hash hash;
|
||||||
|
crypto::cn_slow_hash(&m_data, sizeof(m_data), hash);
|
||||||
|
return hash == m_expected_hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
data_t m_data;
|
||||||
|
crypto::hash m_expected_hash;
|
||||||
|
};
|
|
@ -8,6 +8,7 @@
|
||||||
// tests
|
// tests
|
||||||
#include "construct_tx.h"
|
#include "construct_tx.h"
|
||||||
#include "check_ring_signature.h"
|
#include "check_ring_signature.h"
|
||||||
|
#include "cn_slow_hash.h"
|
||||||
#include "derive_public_key.h"
|
#include "derive_public_key.h"
|
||||||
#include "derive_secret_key.h"
|
#include "derive_secret_key.h"
|
||||||
#include "generate_key_derivation.h"
|
#include "generate_key_derivation.h"
|
||||||
|
@ -56,6 +57,8 @@ int main(int argc, char** argv)
|
||||||
TEST_PERFORMANCE0(test_derive_public_key);
|
TEST_PERFORMANCE0(test_derive_public_key);
|
||||||
TEST_PERFORMANCE0(test_derive_secret_key);
|
TEST_PERFORMANCE0(test_derive_secret_key);
|
||||||
|
|
||||||
|
TEST_PERFORMANCE0(test_cn_slow_hash);
|
||||||
|
|
||||||
std::cout << "Tests finished. Elapsed time: " << timer.elapsed_ms() / 1000 << " sec" << std::endl;
|
std::cout << "Tests finished. Elapsed time: " << timer.elapsed_ms() / 1000 << " sec" << std::endl;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -0,0 +1,140 @@
|
||||||
|
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||||
|
// Distributed under the MIT/X11 software license, see the accompanying
|
||||||
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
#include "cryptonote_core/checkpoints.cpp"
|
||||||
|
|
||||||
|
using namespace cryptonote;
|
||||||
|
|
||||||
|
|
||||||
|
TEST(checkpoints_is_alternative_block_allowed, handles_empty_checkpoins)
|
||||||
|
{
|
||||||
|
checkpoints cp;
|
||||||
|
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(0, 0));
|
||||||
|
|
||||||
|
ASSERT_TRUE(cp.is_alternative_block_allowed(1, 1));
|
||||||
|
ASSERT_TRUE(cp.is_alternative_block_allowed(1, 9));
|
||||||
|
ASSERT_TRUE(cp.is_alternative_block_allowed(9, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(checkpoints_is_alternative_block_allowed, handles_one_checkpoint)
|
||||||
|
{
|
||||||
|
checkpoints cp;
|
||||||
|
cp.add_checkpoint(5, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||||
|
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(0, 0));
|
||||||
|
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(1, 1));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(1, 4));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(1, 5));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(1, 6));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(1, 9));
|
||||||
|
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(4, 1));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(4, 4));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(4, 5));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(4, 6));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(4, 9));
|
||||||
|
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(5, 1));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(5, 4));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(5, 5));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(5, 6));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(5, 9));
|
||||||
|
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(6, 1));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(6, 4));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(6, 5));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(6, 6));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(6, 9));
|
||||||
|
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(9, 1));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(9, 4));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(9, 5));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(9, 6));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(9, 9));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(checkpoints_is_alternative_block_allowed, handles_two_and_more_checkpoints)
|
||||||
|
{
|
||||||
|
checkpoints cp;
|
||||||
|
cp.add_checkpoint(5, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||||
|
cp.add_checkpoint(9, "0000000000000000000000000000000000000000000000000000000000000000");
|
||||||
|
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(0, 0));
|
||||||
|
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(1, 1));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(1, 4));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(1, 5));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(1, 6));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(1, 8));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(1, 9));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(1, 10));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(1, 11));
|
||||||
|
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(4, 1));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(4, 4));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(4, 5));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(4, 6));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(4, 8));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(4, 9));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(4, 10));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(4, 11));
|
||||||
|
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(5, 1));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(5, 4));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(5, 5));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(5, 6));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(5, 8));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(5, 9));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(5, 10));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(5, 11));
|
||||||
|
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(6, 1));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(6, 4));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(6, 5));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(6, 6));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(6, 8));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(6, 9));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(6, 10));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(6, 11));
|
||||||
|
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(8, 1));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(8, 4));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(8, 5));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(8, 6));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(8, 8));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(8, 9));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(8, 10));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(8, 11));
|
||||||
|
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(9, 1));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(9, 4));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(9, 5));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(9, 6));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(9, 8));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(9, 9));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(9, 10));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(9, 11));
|
||||||
|
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(10, 1));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(10, 4));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(10, 5));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(10, 6));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(10, 8));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(10, 9));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(10, 10));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(10, 11));
|
||||||
|
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(11, 1));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(11, 4));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(11, 5));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(11, 6));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(11, 8));
|
||||||
|
ASSERT_FALSE(cp.is_alternative_block_allowed(11, 9));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(11, 10));
|
||||||
|
ASSERT_TRUE (cp.is_alternative_block_allowed(11, 11));
|
||||||
|
}
|
Loading…
Reference in New Issue