aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--contrib/epee/include/misc_log_ex.h2
-rw-r--r--contrib/epee/include/net/http_base.h12
-rw-r--r--contrib/epee/include/net/http_client.h95
-rw-r--r--contrib/epee/include/net/http_protocol_handler.h1
-rw-r--r--contrib/epee/include/net/http_protocol_handler.inl7
-rw-r--r--contrib/epee/include/net/http_server_impl_base.h4
-rw-r--r--contrib/epee/include/storages/http_abstract_invoke.h11
-rw-r--r--contrib/epee/src/CMakeLists.txt10
-rw-r--r--contrib/epee/src/http_auth.cpp2
-rw-r--r--external/db_drivers/liblmdb/mdb.c20
-rw-r--r--external/easylogging++/easylogging++.h6
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/blockchain_db/CMakeLists.txt1
-rw-r--r--src/blockchain_db/berkeleydb/db_bdb.cpp2
-rw-r--r--src/blockchain_db/blockchain_db.cpp2
-rw-r--r--src/blockchain_db/blockchain_db.h6
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp2
-rw-r--r--src/blockchain_utilities/blockchain_import.cpp2
-rw-r--r--src/blockchain_utilities/blocksdat_file.h4
-rw-r--r--src/blockchain_utilities/bootstrap_file.h2
-rw-r--r--src/blockchain_utilities/bootstrap_serialization.h4
-rw-r--r--src/blockchain_utilities/cn_deserialize.cpp4
-rw-r--r--src/blocks/blockexports.c9
-rw-r--r--src/common/CMakeLists.txt4
-rw-r--r--src/common/command_line.cpp1
-rw-r--r--src/common/command_line.h1
-rw-r--r--src/common/common_fwd.h41
-rw-r--r--src/common/dns_utils.cpp2
-rw-r--r--src/common/dns_utils.h2
-rw-r--r--src/common/password.cpp (renamed from src/wallet/password_container.cpp)27
-rw-r--r--src/common/password.h (renamed from src/wallet/password_container.h)31
-rw-r--r--src/common/rpc_client.h6
-rw-r--r--src/cryptonote_basic/CMakeLists.txt73
-rw-r--r--src/cryptonote_basic/account.cpp (renamed from src/cryptonote_core/account.cpp)4
-rw-r--r--src/cryptonote_basic/account.h (renamed from src/cryptonote_core/account.h)2
-rw-r--r--src/cryptonote_basic/account_boost_serialization.h (renamed from src/cryptonote_core/account_boost_serialization.h)2
-rw-r--r--src/cryptonote_basic/checkpoints.cpp (renamed from src/cryptonote_core/checkpoints.cpp)0
-rw-r--r--src/cryptonote_basic/checkpoints.h (renamed from src/cryptonote_core/checkpoints.h)0
-rw-r--r--src/cryptonote_basic/connection_context.h (renamed from src/cryptonote_core/connection_context.h)0
-rw-r--r--src/cryptonote_basic/cryptonote_basic.h (renamed from src/cryptonote_core/cryptonote_basic.h)0
-rw-r--r--src/cryptonote_basic/cryptonote_basic_impl.cpp (renamed from src/cryptonote_core/cryptonote_basic_impl.cpp)0
-rw-r--r--src/cryptonote_basic/cryptonote_basic_impl.h (renamed from src/cryptonote_core/cryptonote_basic_impl.h)0
-rw-r--r--src/cryptonote_basic/cryptonote_boost_serialization.h (renamed from src/cryptonote_core/cryptonote_boost_serialization.h)0
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.cpp (renamed from src/cryptonote_core/cryptonote_format_utils.cpp)450
-rw-r--r--src/cryptonote_basic/cryptonote_format_utils.h (renamed from src/cryptonote_core/cryptonote_format_utils.h)63
-rw-r--r--src/cryptonote_basic/cryptonote_stat_info.h (renamed from src/cryptonote_core/cryptonote_stat_info.h)0
-rw-r--r--src/cryptonote_basic/difficulty.cpp (renamed from src/cryptonote_core/difficulty.cpp)0
-rw-r--r--src/cryptonote_basic/difficulty.h (renamed from src/cryptonote_core/difficulty.h)0
-rw-r--r--src/cryptonote_basic/hardfork.cpp (renamed from src/cryptonote_core/hardfork.cpp)2
-rw-r--r--src/cryptonote_basic/hardfork.h (renamed from src/cryptonote_core/hardfork.h)2
-rw-r--r--src/cryptonote_basic/miner.cpp807
-rw-r--r--src/cryptonote_basic/miner.h (renamed from src/cryptonote_core/miner.h)53
-rw-r--r--src/cryptonote_basic/tx_extra.h (renamed from src/cryptonote_core/tx_extra.h)0
-rw-r--r--src/cryptonote_basic/verification_context.h (renamed from src/cryptonote_core/verification_context.h)0
-rw-r--r--src/cryptonote_core/CMakeLists.txt23
-rw-r--r--src/cryptonote_core/blockchain.cpp11
-rw-r--r--src/cryptonote_core/blockchain.h12
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp4
-rw-r--r--src/cryptonote_core/cryptonote_core.h6
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.cpp493
-rw-r--r--src/cryptonote_core/cryptonote_tx_utils.h101
-rw-r--r--src/cryptonote_core/miner.cpp414
-rw-r--r--src/cryptonote_core/tx_pool.cpp4
-rw-r--r--src/cryptonote_core/tx_pool.h4
-rw-r--r--src/cryptonote_protocol/CMakeLists.txt2
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_defs.h2
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.h6
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl2
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler_common.h2
-rw-r--r--src/daemon/command_parser_executor.cpp17
-rw-r--r--src/daemon/command_parser_executor.h5
-rw-r--r--src/daemon/command_server.cpp6
-rw-r--r--src/daemon/command_server.h4
-rw-r--r--src/daemon/daemon.cpp4
-rw-r--r--src/daemon/main.cpp23
-rw-r--r--src/daemon/rpc_command_executor.cpp17
-rw-r--r--src/daemon/rpc_command_executor.h7
-rw-r--r--src/mnemonics/CMakeLists.txt2
-rw-r--r--src/p2p/CMakeLists.txt1
-rw-r--r--src/ringct/CMakeLists.txt1
-rw-r--r--src/ringct/rctSigs.cpp2
-rw-r--r--src/rpc/CMakeLists.txt8
-rw-r--r--src/rpc/core_rpc_server.cpp58
-rw-r--r--src/rpc/core_rpc_server.h8
-rw-r--r--src/rpc/core_rpc_server_commands_defs.h8
-rw-r--r--src/rpc/rpc_args.cpp96
-rw-r--r--src/rpc/rpc_args.h67
-rw-r--r--src/simplewallet/simplewallet.cpp10
-rw-r--r--src/simplewallet/simplewallet.h6
-rw-r--r--src/wallet/CMakeLists.txt3
-rw-r--r--src/wallet/api/pending_transaction.cpp5
-rw-r--r--src/wallet/api/unsigned_transaction.cpp5
-rw-r--r--src/wallet/api/wallet.cpp8
-rw-r--r--src/wallet/api/wallet_manager.cpp2
-rw-r--r--src/wallet/wallet2.cpp45
-rw-r--r--src/wallet/wallet2.h18
-rw-r--r--src/wallet/wallet2_api.h2
-rw-r--r--src/wallet/wallet_errors.h2
-rw-r--r--src/wallet/wallet_rpc_server.cpp91
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h2
-rw-r--r--tests/CMakeLists.txt38
-rw-r--r--tests/core_proxy/core_proxy.h4
-rw-r--r--tests/core_tests/chaingen.cpp8
-rw-r--r--tests/core_tests/chaingen.h10
-rw-r--r--tests/core_tests/chaingen001.cpp4
-rw-r--r--tests/core_tests/transaction_tests.cpp6
-rw-r--r--tests/daemon_tests/transfers.cpp2
-rw-r--r--tests/difficulty/difficulty.cpp2
-rw-r--r--tests/functional_tests/transactions_flow_test.cpp2
-rw-r--r--tests/hash-target.cpp2
-rw-r--r--tests/performance_tests/check_tx_signature.h6
-rw-r--r--tests/performance_tests/cn_slow_hash.h2
-rw-r--r--tests/performance_tests/construct_tx.h6
-rw-r--r--tests/performance_tests/derive_public_key.h2
-rw-r--r--tests/performance_tests/derive_secret_key.h2
-rw-r--r--tests/performance_tests/ge_frombytes_vartime.h2
-rw-r--r--tests/performance_tests/generate_key_derivation.h2
-rw-r--r--tests/performance_tests/generate_key_image.h2
-rw-r--r--tests/performance_tests/generate_key_image_helper.h6
-rw-r--r--tests/performance_tests/generate_keypair.h2
-rw-r--r--tests/performance_tests/is_out_to_acc.h6
-rw-r--r--tests/performance_tests/multi_tx_test_base.h6
-rw-r--r--tests/performance_tests/single_tx_test_base.h6
-rw-r--r--tests/unit_tests/CMakeLists.txt4
-rw-r--r--tests/unit_tests/base58.cpp2
-rw-r--r--tests/unit_tests/block_reward.cpp2
-rw-r--r--tests/unit_tests/blockchain_db.cpp2
-rw-r--r--tests/unit_tests/canonical_amounts.cpp2
-rw-r--r--tests/unit_tests/checkpoints.cpp2
-rw-r--r--tests/unit_tests/decompose_amount_into_digits.cpp2
-rw-r--r--tests/unit_tests/hardfork.cpp2
-rw-r--r--tests/unit_tests/http.cpp (renamed from tests/unit_tests/http_auth.cpp)34
-rw-r--r--tests/unit_tests/parse_amount.cpp2
-rw-r--r--tests/unit_tests/serialization.cpp4
-rw-r--r--tests/unit_tests/test_tx_utils.cpp (renamed from tests/unit_tests/test_format_utils.cpp)2
-rw-r--r--tests/unit_tests/varint.cpp4
137 files changed, 2267 insertions, 1327 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 541a4493f..f59493345 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -194,6 +194,7 @@ endif()
if (BUILD_SHARED_LIBS)
message(STATUS "Building internal libraries with position independent code")
set(PIC_FLAG "-fPIC")
+ add_definitions("-DBUILD_SHARED_LIBS")
else()
message(STATUS "Building internal libraries as static")
endif()
diff --git a/contrib/epee/include/misc_log_ex.h b/contrib/epee/include/misc_log_ex.h
index fbfd6941f..b1685f382 100644
--- a/contrib/epee/include/misc_log_ex.h
+++ b/contrib/epee/include/misc_log_ex.h
@@ -51,7 +51,9 @@
#define ELPP_THREAD_SAFE
#define ELPP_DEFAULT_LOG_FILE ""
+#ifndef __ANDROID__
#define ELPP_STACKTRACE_ON_CRASH 0
+#endif
#define ELPP_DISABLE_DEFAULT_CRASH_HANDLING
#define ELPP_FEATURE_CRASH_LOG 1
#define ELPP_DISABLE_CHECK_MACROS
diff --git a/contrib/epee/include/net/http_base.h b/contrib/epee/include/net/http_base.h
index d8e31521f..e5aa06cb4 100644
--- a/contrib/epee/include/net/http_base.h
+++ b/contrib/epee/include/net/http_base.h
@@ -29,6 +29,9 @@
#pragma once
#include <boost/lexical_cast.hpp>
#include <boost/regex.hpp>
+#include <boost/utility/string_ref.hpp>
+#include <string>
+#include <utility>
#include "string_tools.h"
@@ -90,6 +93,15 @@ namespace net_utils
return std::string();
}
+ static inline void add_field(std::string& out, const boost::string_ref name, const boost::string_ref value)
+ {
+ out.append(name.data(), name.size()).append(": ");
+ out.append(value.data(), value.size()).append("\r\n");
+ }
+ static inline void add_field(std::string& out, const std::pair<std::string, std::string>& field)
+ {
+ add_field(out, field.first, field.second);
+ }
struct http_header_info
diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h
index c5aeb9251..3d8c759cd 100644
--- a/contrib/epee/include/net/http_client.h
+++ b/contrib/epee/include/net/http_client.h
@@ -30,6 +30,8 @@
#include <boost/shared_ptr.hpp>
#include <boost/regex.hpp>
#include <boost/lexical_cast.hpp>
+#include <boost/optional/optional.hpp>
+#include <boost/utility/string_ref.hpp>
//#include <mbstring.h>
#include <algorithm>
#include <cctype>
@@ -45,6 +47,7 @@
#include "string_tools.h"
#include "reg_exp_definer.h"
#include "http_base.h"
+#include "http_auth.h"
#include "to_nonconst_iterator.h"
#include "net_parse_helpers.h"
@@ -236,9 +239,6 @@ using namespace std;
class http_simple_client: public i_target_handler
{
- public:
-
-
private:
enum reciev_machine_state
{
@@ -263,6 +263,7 @@ using namespace std;
blocked_mode_client m_net_client;
std::string m_host_buff;
std::string m_port;
+ http_client_auth m_auth;
std::string m_header_cache;
http_response_info m_response_info;
size_t m_len_in_summary;
@@ -280,6 +281,7 @@ using namespace std;
, m_net_client()
, m_host_buff()
, m_port()
+ , m_auth()
, m_header_cache()
, m_response_info()
, m_len_in_summary(0)
@@ -291,21 +293,22 @@ using namespace std;
, m_lock()
{}
- bool set_server(const std::string& address)
+ bool set_server(const std::string& address, boost::optional<login> user)
{
http::url_content parsed{};
const bool r = parse_url(address, parsed);
CHECK_AND_ASSERT_MES(r, false, "failed to parse url: " << address);
- set_server(std::move(parsed.host), std::to_string(parsed.port));
+ set_server(std::move(parsed.host), std::to_string(parsed.port), std::move(user));
return true;
}
- void set_server(std::string host, std::string port)
+ void set_server(std::string host, std::string port, boost::optional<login> user)
{
CRITICAL_REGION_LOCAL(m_lock);
disconnect();
m_host_buff = std::move(host);
m_port = std::move(port);
+ m_auth = user ? http_client_auth{std::move(*user)} : http_client_auth{};
}
bool connect(std::chrono::milliseconds timeout)
@@ -335,14 +338,14 @@ using namespace std;
}
//---------------------------------------------------------------------------
inline
- bool invoke_get(const std::string& uri, std::chrono::milliseconds timeout, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
+ bool invoke_get(const boost::string_ref uri, std::chrono::milliseconds timeout, const std::string& body = std::string(), const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
{
CRITICAL_REGION_LOCAL(m_lock);
return invoke(uri, "GET", body, timeout, ppresponse_info, additional_params);
}
//---------------------------------------------------------------------------
- inline bool invoke(const std::string& uri, const std::string& method, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
+ inline bool invoke(const boost::string_ref uri, const boost::string_ref method, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
{
CRITICAL_REGION_LOCAL(m_lock);
if(!is_connected())
@@ -354,32 +357,64 @@ using namespace std;
return false;
}
}
- m_response_info.clear();
- std::string req_buff = method + " ";
- req_buff += uri + " HTTP/1.1\r\n" +
- "Host: "+ m_host_buff +"\r\n" + "Content-Length: " + boost::lexical_cast<std::string>(body.size()) + "\r\n";
+ std::string req_buff{};
+ req_buff.reserve(2048);
+ req_buff.append(method.data(), method.size()).append(" ").append(uri.data(), uri.size()).append(" HTTP/1.1\r\n");
+ add_field(req_buff, "Host", m_host_buff);
+ add_field(req_buff, "Content-Length", std::to_string(body.size()));
//handle "additional_params"
- for(fields_list::const_iterator it = additional_params.begin(); it!=additional_params.end(); it++)
- req_buff += it->first + ": " + it->second + "\r\n";
- req_buff += "\r\n";
- //--
-
- bool res = m_net_client.send(req_buff, timeout);
- CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
- if(body.size())
- res = m_net_client.send(body, timeout);
- CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
-
- if(ppresponse_info)
- *ppresponse_info = &m_response_info;
-
- m_state = reciev_machine_state_header;
- return handle_reciev(timeout);
+ for(const auto& field : additional_params)
+ add_field(req_buff, field);
+
+ for (unsigned sends = 0; sends < 2; ++sends)
+ {
+ const std::size_t initial_size = req_buff.size();
+ const auto auth = m_auth.get_auth_field(method, uri);
+ if (auth)
+ add_field(req_buff, *auth);
+
+ req_buff += "\r\n";
+ //--
+
+ bool res = m_net_client.send(req_buff, timeout);
+ CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
+ if(body.size())
+ res = m_net_client.send(body, timeout);
+ CHECK_AND_ASSERT_MES(res, false, "HTTP_CLIENT: Failed to SEND");
+
+
+ m_response_info.clear();
+ m_state = reciev_machine_state_header;
+ if (!handle_reciev(timeout))
+ return false;
+ if (m_response_info.m_response_code != 401)
+ {
+ if(ppresponse_info)
+ *ppresponse_info = std::addressof(m_response_info);
+ return true;
+ }
+
+ switch (m_auth.handle_401(m_response_info))
+ {
+ case http_client_auth::kSuccess:
+ break;
+ case http_client_auth::kBadPassword:
+ sends = 2;
+ break;
+ default:
+ case http_client_auth::kParseFailure:
+ LOG_ERROR("Bad server response for authentication");
+ return false;
+ }
+ req_buff.resize(initial_size); // rollback for new auth generation
+ }
+ LOG_ERROR("Client has incorrect username/password for server requiring authentication");
+ return false;
}
//---------------------------------------------------------------------------
- inline bool invoke_post(const std::string& uri, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
+ inline bool invoke_post(const boost::string_ref uri, const std::string& body, std::chrono::milliseconds timeout, const http_response_info** ppresponse_info = NULL, const fields_list& additional_params = fields_list())
{
CRITICAL_REGION_LOCAL(m_lock);
return invoke(uri, "POST", body, timeout, ppresponse_info, additional_params);
@@ -730,7 +765,7 @@ using namespace std;
else if(result[i++].matched)//"User-Agent"
body_info.m_user_agent = result[field_val];
else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!)
- {;}
+ body_info.m_etc_fields.emplace_back(result[11], result[field_val]);
else
{CHECK_AND_ASSERT_MES(false, false, "http_stream_filter::parse_cached_header() not matched last entry in:"<<m_cache_to_process);}
diff --git a/contrib/epee/include/net/http_protocol_handler.h b/contrib/epee/include/net/http_protocol_handler.h
index c2e44c536..babe49ad7 100644
--- a/contrib/epee/include/net/http_protocol_handler.h
+++ b/contrib/epee/include/net/http_protocol_handler.h
@@ -54,7 +54,6 @@ namespace net_utils
struct http_server_config
{
std::string m_folder;
- std::string m_required_user_agent;
boost::optional<login> m_user;
critical_section m_lock;
};
diff --git a/contrib/epee/include/net/http_protocol_handler.inl b/contrib/epee/include/net/http_protocol_handler.inl
index 5bfaf4767..d9eca2479 100644
--- a/contrib/epee/include/net/http_protocol_handler.inl
+++ b/contrib/epee/include/net/http_protocol_handler.inl
@@ -390,13 +390,6 @@ namespace net_utils
return false;
}
- if (!m_config.m_required_user_agent.empty() && m_query_info.m_header_info.m_user_agent != m_config.m_required_user_agent)
- {
- LOG_ERROR("simple_http_connection_handler<t_connection_context>::analize_cached_request_header_and_invoke_state(): unexpected user agent: " << m_query_info.m_header_info.m_user_agent);
- m_state = http_state_error;
- return false;
- }
-
m_cache.erase(0, pos);
std::string req_command_str = m_query_info.m_full_request_str;
diff --git a/contrib/epee/include/net/http_server_impl_base.h b/contrib/epee/include/net/http_server_impl_base.h
index f2a580167..2a762b3ca 100644
--- a/contrib/epee/include/net/http_server_impl_base.h
+++ b/contrib/epee/include/net/http_server_impl_base.h
@@ -56,7 +56,7 @@ namespace epee
{}
bool init(const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0",
- std::string user_agent = "", boost::optional<net_utils::http::login> user = boost::none)
+ boost::optional<net_utils::http::login> user = boost::none)
{
//set self as callback handler
@@ -65,8 +65,6 @@ namespace epee
//here set folder for hosting reqests
m_net_server.get_config_object().m_folder = "";
- // workaround till we get auth/encryption
- m_net_server.get_config_object().m_required_user_agent = std::move(user_agent);
m_net_server.get_config_object().m_user = std::move(user);
LOG_PRINT_L0("Binding on " << bind_ip << ":" << bind_port);
diff --git a/contrib/epee/include/storages/http_abstract_invoke.h b/contrib/epee/include/storages/http_abstract_invoke.h
index 36177c7e0..47981acb3 100644
--- a/contrib/epee/include/storages/http_abstract_invoke.h
+++ b/contrib/epee/include/storages/http_abstract_invoke.h
@@ -26,6 +26,9 @@
//
#pragma once
+#include <boost/utility/string_ref.hpp>
+#include <chrono>
+#include <string>
#include "portable_storage_template_helper.h"
#include "net/http_base.h"
#include "net/http_server_handlers_map2.h"
@@ -35,7 +38,7 @@ namespace epee
namespace net_utils
{
template<class t_request, class t_response, class t_transport>
- bool invoke_http_json(const std::string& uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& method = "GET")
+ bool invoke_http_json(const boost::string_ref uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const boost::string_ref method = "GET")
{
std::string req_param;
if(!serialization::store_t_to_json(out_struct, req_param))
@@ -66,7 +69,7 @@ namespace epee
template<class t_request, class t_response, class t_transport>
- bool invoke_http_bin(const std::string& uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& method = "GET")
+ bool invoke_http_bin(const boost::string_ref uri, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const boost::string_ref method = "GET")
{
std::string req_param;
if(!serialization::store_t_to_binary(out_struct, req_param))
@@ -95,7 +98,7 @@ namespace epee
}
template<class t_request, class t_response, class t_transport>
- bool invoke_http_json_rpc(const std::string& uri, std::string method_name, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& http_method = "GET", const std::string& req_id = "0")
+ bool invoke_http_json_rpc(const boost::string_ref uri, std::string method_name, const t_request& out_struct, t_response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const boost::string_ref http_method = "GET", const std::string& req_id = "0")
{
epee::json_rpc::request<t_request> req_t = AUTO_VAL_INIT(req_t);
req_t.jsonrpc = "2.0";
@@ -117,7 +120,7 @@ namespace epee
}
template<class t_command, class t_transport>
- bool invoke_http_json_rpc(const std::string& uri, typename t_command::request& out_struct, typename t_command::response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const std::string& http_method = "GET", const std::string& req_id = "0")
+ bool invoke_http_json_rpc(const boost::string_ref uri, typename t_command::request& out_struct, typename t_command::response& result_struct, t_transport& transport, std::chrono::milliseconds timeout = std::chrono::seconds(5), const boost::string_ref http_method = "GET", const std::string& req_id = "0")
{
return invoke_http_json_rpc(uri, t_command::methodname(), out_struct, result_struct, transport, timeout, http_method, req_id);
}
diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt
index 93c9a94f7..7d2c24e96 100644
--- a/contrib/epee/src/CMakeLists.txt
+++ b/contrib/epee/src/CMakeLists.txt
@@ -27,6 +27,7 @@
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
add_library(epee STATIC http_auth.cpp mlog.cpp)
+
# Build and install libepee if we're building for GUI
if (BUILD_GUI_DEPS)
if(IOS)
@@ -36,4 +37,11 @@ if (BUILD_GUI_DEPS)
endif()
install(TARGETS epee
ARCHIVE DESTINATION ${lib_folder})
-endif() \ No newline at end of file
+endif()
+
+target_link_libraries(epee
+ PUBLIC
+ crypto
+ ${Boost_FILESYSTEM_LIBRARY}
+ PRIVATE
+ ${EXTRA_LIBRARIES})
diff --git a/contrib/epee/src/http_auth.cpp b/contrib/epee/src/http_auth.cpp
index 7fd32dabc..4d2523e1f 100644
--- a/contrib/epee/src/http_auth.cpp
+++ b/contrib/epee/src/http_auth.cpp
@@ -362,7 +362,7 @@ namespace
server_parameters best{};
- const std::list<field>& fields = response.m_additional_fields;
+ const std::list<field>& fields = response.m_header_info.m_etc_fields;
auto current = fields.begin();
const auto end = fields.end();
while (true)
diff --git a/external/db_drivers/liblmdb/mdb.c b/external/db_drivers/liblmdb/mdb.c
index d778037b0..c2408f917 100644
--- a/external/db_drivers/liblmdb/mdb.c
+++ b/external/db_drivers/liblmdb/mdb.c
@@ -809,6 +809,16 @@ typedef struct MDB_txbody {
uint32_t mtb_magic;
/** Format of this lock file. Must be set to #MDB_LOCK_FORMAT. */
uint32_t mtb_format;
+ /** The ID of the last transaction committed to the database.
+ * This is recorded here only for convenience; the value can always
+ * be determined by reading the main database meta pages.
+ */
+ volatile txnid_t mtb_txnid;
+ /** The number of slots that have been used in the reader table.
+ * This always records the maximum count, it is not decremented
+ * when readers release their slots.
+ */
+ volatile unsigned mtb_numreaders;
#if defined(_WIN32) || defined(MDB_USE_POSIX_SEM)
char mtb_rmname[MNAME_LEN];
#elif defined(MDB_USE_SYSV_SEM)
@@ -820,16 +830,6 @@ typedef struct MDB_txbody {
*/
mdb_mutex_t mtb_rmutex;
#endif
- /** The ID of the last transaction committed to the database.
- * This is recorded here only for convenience; the value can always
- * be determined by reading the main database meta pages.
- */
- volatile txnid_t mtb_txnid;
- /** The number of slots that have been used in the reader table.
- * This always records the maximum count, it is not decremented
- * when readers release their slots.
- */
- volatile unsigned mtb_numreaders;
} MDB_txbody;
/** The actual reader table definition. */
diff --git a/external/easylogging++/easylogging++.h b/external/easylogging++/easylogging++.h
index d28152667..24e271e80 100644
--- a/external/easylogging++/easylogging++.h
+++ b/external/easylogging++/easylogging++.h
@@ -281,11 +281,11 @@ ELPP_INTERNAL_DEBUGGING_OUT_INFO << ELPP_INTERNAL_DEBUGGING_MSG(internalInfoStre
(ELPP_COMPILER_GCC || ELPP_COMPILER_CLANG || ELPP_COMPILER_INTEL || (ELPP_COMPILER_MSVC && _MSC_VER >= 1800))
// Logging Enable/Disable macros
#define ELPP_LOGGING_ENABLED (!defined(ELPP_DISABLE_LOGS))
-#if (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED) && ((defined(_DEBUG)) || (!defined(NDEBUG))))
+#if (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED))
# define ELPP_DEBUG_LOG 1
#else
# define ELPP_DEBUG_LOG 0
-#endif // (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED) && ((defined(_DEBUG)) || (!defined(NDEBUG))))
+#endif // (!defined(ELPP_DISABLE_DEBUG_LOGS) && (ELPP_LOGGING_ENABLED))
#if (!defined(ELPP_DISABLE_INFO_LOGS) && (ELPP_LOGGING_ENABLED))
# define ELPP_INFO_LOG 1
#else
@@ -3988,10 +3988,12 @@ inline void FUNCTION_NAME(const T&);
}
void setThreadName(const std::string &name) {
+ const base::threading::ScopedLock scopedLock(lock());
m_threadNames[base::threading::getCurrentThreadId()] = name;
}
std::string getThreadName(const std::string& name) {
+ const base::threading::ScopedLock scopedLock(lock());
std::map<std::string, std::string>::const_iterator it = m_threadNames.find(name);
if (it == m_threadNames.end())
return name;
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index fc7d60e4c..c2f0bb6e3 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -99,6 +99,7 @@ endfunction ()
add_subdirectory(common)
add_subdirectory(crypto)
add_subdirectory(ringct)
+add_subdirectory(cryptonote_basic)
add_subdirectory(cryptonote_core)
add_subdirectory(blockchain_db)
add_subdirectory(mnemonics)
diff --git a/src/blockchain_db/CMakeLists.txt b/src/blockchain_db/CMakeLists.txt
index cefe93ebe..bee057891 100644
--- a/src/blockchain_db/CMakeLists.txt
+++ b/src/blockchain_db/CMakeLists.txt
@@ -63,6 +63,7 @@ target_link_libraries(blockchain_db
PUBLIC
common
crypto
+ ringct
${LMDB_LIBRARY}
${BDB_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
diff --git a/src/blockchain_db/berkeleydb/db_bdb.cpp b/src/blockchain_db/berkeleydb/db_bdb.cpp
index 57d8371bd..b48d998dc 100644
--- a/src/blockchain_db/berkeleydb/db_bdb.cpp
+++ b/src/blockchain_db/berkeleydb/db_bdb.cpp
@@ -31,7 +31,7 @@
#include <memory> // std::unique_ptr
#include <cstring> // memcpy
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
#include "crypto/crypto.h"
#include "profile_tools.h"
diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp
index bd1a38ec3..1cb0ada0c 100644
--- a/src/blockchain_db/blockchain_db.cpp
+++ b/src/blockchain_db/blockchain_db.cpp
@@ -29,7 +29,7 @@
#include <boost/range/adaptor/reversed.hpp>
#include "blockchain_db.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
#include "profile_tools.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h
index 455e0c811..3fdb62a7b 100644
--- a/src/blockchain_db/blockchain_db.h
+++ b/src/blockchain_db/blockchain_db.h
@@ -34,9 +34,9 @@
#include <string>
#include <exception>
#include "crypto/hash.h"
-#include "cryptonote_core/cryptonote_basic.h"
-#include "cryptonote_core/difficulty.h"
-#include "cryptonote_core/hardfork.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+#include "cryptonote_basic/difficulty.h"
+#include "cryptonote_basic/hardfork.h"
/** \file
* Cryptonote Blockchain Database Interface
diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index 1cfcf3a9e..863f54246 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -34,7 +34,7 @@
#include <cstring> // memcpy
#include <random>
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
#include "crypto/crypto.h"
#include "profile_tools.h"
diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp
index f21673b89..6f5520b59 100644
--- a/src/blockchain_utilities/blockchain_import.cpp
+++ b/src/blockchain_utilities/blockchain_import.cpp
@@ -34,7 +34,7 @@
#include <boost/filesystem.hpp>
#include "bootstrap_file.h"
#include "bootstrap_serialization.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
#include "serialization/binary_utils.h" // dump_binary(), parse_binary()
#include "serialization/json_utils.h" // dump_json()
#include "include_base_utils.h"
diff --git a/src/blockchain_utilities/blocksdat_file.h b/src/blockchain_utilities/blocksdat_file.h
index ed821cd6d..c1f26c0a2 100644
--- a/src/blockchain_utilities/blocksdat_file.h
+++ b/src/blockchain_utilities/blocksdat_file.h
@@ -34,8 +34,8 @@
#include <boost/iostreams/filtering_streambuf.hpp>
-#include "cryptonote_core/cryptonote_basic.h"
-#include "cryptonote_core/cryptonote_boost_serialization.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_boost_serialization.h"
#include "cryptonote_core/blockchain.h"
#include "blockchain_db/blockchain_db.h"
#include "blockchain_db/lmdb/db_lmdb.h"
diff --git a/src/blockchain_utilities/bootstrap_file.h b/src/blockchain_utilities/bootstrap_file.h
index 0bbe28f17..67d849a77 100644
--- a/src/blockchain_utilities/bootstrap_file.h
+++ b/src/blockchain_utilities/bootstrap_file.h
@@ -34,7 +34,7 @@
#include <boost/iostreams/filtering_streambuf.hpp>
-#include "cryptonote_core/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_core/blockchain.h"
#include <algorithm>
diff --git a/src/blockchain_utilities/bootstrap_serialization.h b/src/blockchain_utilities/bootstrap_serialization.h
index a7d88907f..008633d9b 100644
--- a/src/blockchain_utilities/bootstrap_serialization.h
+++ b/src/blockchain_utilities/bootstrap_serialization.h
@@ -28,8 +28,8 @@
#pragma once
-#include "cryptonote_core/cryptonote_boost_serialization.h"
-#include "cryptonote_core/difficulty.h"
+#include "cryptonote_basic/cryptonote_boost_serialization.h"
+#include "cryptonote_basic/difficulty.h"
namespace cryptonote
diff --git a/src/blockchain_utilities/cn_deserialize.cpp b/src/blockchain_utilities/cn_deserialize.cpp
index ae8e38435..7913de011 100644
--- a/src/blockchain_utilities/cn_deserialize.cpp
+++ b/src/blockchain_utilities/cn_deserialize.cpp
@@ -26,8 +26,8 @@
// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#include "cryptonote_core/cryptonote_basic.h"
-#include "cryptonote_core/tx_extra.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+#include "cryptonote_basic/tx_extra.h"
#include "cryptonote_core/blockchain.h"
#include "blockchain_utilities.h"
#include "common/command_line.h"
diff --git a/src/blocks/blockexports.c b/src/blocks/blockexports.c
index 26adaad62..477167a12 100644
--- a/src/blocks/blockexports.c
+++ b/src/blocks/blockexports.c
@@ -2,12 +2,19 @@
#if defined(__APPLE__)
#include <mach-o/getsect.h>
-
+#ifdef BUILD_SHARED_LIBS
+#if !defined(__LP64__)
+const struct mach_header _mh_execute_header;
+#else
+const struct mach_header_64 _mh_execute_header;
+#endif
+#else
#if !defined(__LP64__)
extern const struct mach_header _mh_execute_header;
#else
extern const struct mach_header_64 _mh_execute_header;
#endif
+#endif
const unsigned char *get_blocks_dat_start(int testnet)
{
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 1864c7835..c63d9d0ae 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -32,6 +32,7 @@ set(common_sources
dns_utils.cpp
util.cpp
i18n.cpp
+ password.cpp
perf_timer.cpp
task_region.cpp
thread_group.cpp)
@@ -46,6 +47,7 @@ set(common_private_headers
base58.h
boost_serialization_helper.h
command_line.h
+ common_fwd.h
dns_utils.h
http_connection.h
int-util.h
@@ -56,6 +58,7 @@ set(common_private_headers
util.h
varint.h
i18n.h
+ password.h
perf_timer.h
stack_trace.h
task_region.h
@@ -69,6 +72,7 @@ monero_add_library(common
${common_private_headers})
target_link_libraries(common
PUBLIC
+ epee
crypto
${UNBOUND_LIBRARY}
${LIBUNWIND_LIBRARIES}
diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp
index d95859256..c3df5c096 100644
--- a/src/common/command_line.cpp
+++ b/src/common/command_line.cpp
@@ -76,7 +76,6 @@ namespace command_line
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_testnet_data_dir = {"testnet-data-dir", "Specify testnet data directory"};
- const arg_descriptor<std::string> arg_user_agent = {"user-agent", "Restrict RPC use to clients using this user agent"};
const arg_descriptor<bool> arg_test_drop_download = {"test-drop-download", "For net tests: in download, discard ALL blocks instead checking/saving them (very fast)"};
const arg_descriptor<uint64_t> arg_test_drop_download_height = {"test-drop-download-height", "Like test-drop-download but disards only after around certain height", 0};
const arg_descriptor<int> arg_test_dbg_lock_sleep = {"test-dbg-lock-sleep", "Sleep time in ms, defaults to 0 (off), used to debug before/after locking mutex. Values 100 to 1000 are good for tests."};
diff --git a/src/common/command_line.h b/src/common/command_line.h
index 3f0919e99..a09365a6b 100644
--- a/src/common/command_line.h
+++ b/src/common/command_line.h
@@ -207,7 +207,6 @@ namespace command_line
extern const arg_descriptor<bool> arg_version;
extern const arg_descriptor<std::string> arg_data_dir;
extern const arg_descriptor<std::string> arg_testnet_data_dir;
- extern const arg_descriptor<std::string> arg_user_agent;
extern const arg_descriptor<bool> arg_test_drop_download;
extern const arg_descriptor<uint64_t> arg_test_drop_download_height;
extern const arg_descriptor<int> arg_test_dbg_lock_sleep;
diff --git a/src/common/common_fwd.h b/src/common/common_fwd.h
new file mode 100644
index 000000000..5d67251b1
--- /dev/null
+++ b/src/common/common_fwd.h
@@ -0,0 +1,41 @@
+// Copyright (c) 2014-2017, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#pragma once
+
+namespace tools
+{
+ class DNSResolver;
+ struct login;
+ class password_container;
+ class t_http_connection;
+ class task_region;
+ class thread_group;
+}
diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp
index 83259bc70..5ff39574c 100644
--- a/src/common/dns_utils.cpp
+++ b/src/common/dns_utils.cpp
@@ -29,7 +29,7 @@
#include "common/command_line.h"
#include "common/i18n.h"
#include "common/dns_utils.h"
-#include "cryptonote_core/cryptonote_basic_impl.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
#include <cstring>
#include <sstream>
// check local first (in the event of static or in-source compilation of libunbound)
diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h
index 8a63a8129..6ecf5595c 100644
--- a/src/common/dns_utils.h
+++ b/src/common/dns_utils.h
@@ -29,7 +29,7 @@
#include <vector>
#include <string>
-#include "cryptonote_core/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic.h"
namespace tools
{
diff --git a/src/wallet/password_container.cpp b/src/common/password.cpp
index 832b93a1a..bdc9c69c0 100644
--- a/src/wallet/password_container.cpp
+++ b/src/common/password.cpp
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2016, The Monero Project
+// Copyright (c) 2014-2017, The Monero Project
//
// All rights reserved.
//
@@ -28,7 +28,7 @@
//
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
-#include "password_container.h"
+#include "password.h"
#include <iostream>
#include <memory.h>
@@ -245,4 +245,27 @@ namespace tools
return boost::none;
}
+
+ boost::optional<login> login::parse(std::string&& userpass, bool verify, const char* message)
+ {
+ login out{};
+ password_container wipe{std::move(userpass)};
+
+ const auto loc = wipe.password().find(':');
+ if (loc == std::string::npos)
+ {
+ auto result = tools::password_container::prompt(verify, message);
+ if (!result)
+ return boost::none;
+
+ out.password = std::move(*result);
+ }
+ else
+ {
+ out.password = password_container{wipe.password().substr(loc + 1)};
+ }
+
+ out.username = wipe.password().substr(0, loc);
+ return {std::move(out)};
+ }
}
diff --git a/src/wallet/password_container.h b/src/common/password.h
index 9c6faf9c8..12f715df4 100644
--- a/src/wallet/password_container.h
+++ b/src/common/password.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2014-2016, The Monero Project
+// Copyright (c) 2014-2017, The Monero Project
//
// All rights reserved.
//
@@ -64,4 +64,33 @@ namespace tools
//! TODO Custom allocator that locks to RAM?
std::string m_password;
};
+
+ struct login
+ {
+ login() = default;
+
+ /*!
+ Extracts username and password from the format `username:password`. A
+ blank username or password is allowed. If the `:` character is not
+ present, `password_container::prompt` will be called by forwarding the
+ `verify` and `message` arguments.
+
+ \param userpass Is "consumed", and the memory contents are wiped.
+ \param verify is passed to `password_container::prompt` if necessary.
+ \param message is passed to `password_container::prompt` if necessary.
+
+ \return The username and password, or boost::none if
+ `password_container::prompt` fails.
+ */
+ static boost::optional<login> parse(std::string&& userpass, bool verify, const char* message = "Password");
+
+ login(const login&) = delete;
+ login(login&&) = default;
+ ~login() = default;
+ login& operator=(const login&) = delete;
+ login& operator=(login&&) = default;
+
+ std::string username;
+ password_container password;
+ };
}
diff --git a/src/common/rpc_client.h b/src/common/rpc_client.h
index f5ecc8b50..40c103bf3 100644
--- a/src/common/rpc_client.h
+++ b/src/common/rpc_client.h
@@ -28,10 +28,13 @@
#pragma once
+#include <boost/optional/optional.hpp>
+
#include "common/http_connection.h"
#include "common/scoped_message_writer.h"
#include "rpc/core_rpc_server_commands_defs.h"
#include "storages/http_abstract_invoke.h"
+#include "net/http_auth.h"
#include "net/http_client.h"
#include "string_tools.h"
@@ -45,11 +48,12 @@ namespace tools
t_rpc_client(
uint32_t ip
, uint16_t port
+ , boost::optional<epee::net_utils::http::login> user
)
: m_http_client{}
{
m_http_client.set_server(
- epee::string_tools::get_ip_string_from_int32(ip), std::to_string(port)
+ epee::string_tools::get_ip_string_from_int32(ip), std::to_string(port), std::move(user)
);
}
diff --git a/src/cryptonote_basic/CMakeLists.txt b/src/cryptonote_basic/CMakeLists.txt
new file mode 100644
index 000000000..ac8c53f95
--- /dev/null
+++ b/src/cryptonote_basic/CMakeLists.txt
@@ -0,0 +1,73 @@
+# Copyright (c) 2014-2016, The Monero Project
+#
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without modification, are
+# permitted provided that the following conditions are met:
+#
+# 1. Redistributions of source code must retain the above copyright notice, this list of
+# conditions and the following disclaimer.
+#
+# 2. Redistributions in binary form must reproduce the above copyright notice, this list
+# of conditions and the following disclaimer in the documentation and/or other
+# materials provided with the distribution.
+#
+# 3. Neither the name of the copyright holder nor the names of its contributors may be
+# used to endorse or promote products derived from this software without specific
+# prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+# THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+set(cryptonote_basic_sources
+ account.cpp
+ checkpoints.cpp
+ cryptonote_basic_impl.cpp
+ cryptonote_format_utils.cpp
+ difficulty.cpp
+ miner.cpp
+ hardfork.cpp)
+
+set(cryptonote_basic_headers)
+
+set(cryptonote_basic_private_headers
+ account.h
+ account_boost_serialization.h
+ checkpoints.h
+ connection_context.h
+ cryptonote_basic.h
+ cryptonote_basic_impl.h
+ cryptonote_boost_serialization.h
+ cryptonote_format_utils.h
+ cryptonote_stat_info.h
+ difficulty.h
+ miner.h
+ tx_extra.h
+ verification_context.h
+ hardfork.h)
+
+monero_private_headers(cryptonote_basic
+ ${crypto_private_headers})
+monero_add_library(cryptonote_basic
+ ${cryptonote_basic_sources}
+ ${cryptonote_basic_headers}
+ ${cryptonote_basic_private_headers})
+target_link_libraries(cryptonote_basic
+ PUBLIC
+ common
+ crypto
+ ${Boost_DATE_TIME_LIBRARY}
+ ${Boost_PROGRAM_OPTIONS_LIBRARY}
+ ${Boost_SERIALIZATION_LIBRARY}
+ ${Boost_FILESYSTEM_LIBRARY}
+ ${Boost_SYSTEM_LIBRARY}
+ ${Boost_THREAD_LIBRARY}
+ PRIVATE
+ ${EXTRA_LIBRARIES})
diff --git a/src/cryptonote_core/account.cpp b/src/cryptonote_basic/account.cpp
index 8f2db6863..6d1a0a5e7 100644
--- a/src/cryptonote_core/account.cpp
+++ b/src/cryptonote_basic/account.cpp
@@ -38,8 +38,8 @@ extern "C"
{
#include "crypto/keccak.h"
}
-#include "cryptonote_core/cryptonote_basic_impl.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic_impl.h"
+#include "cryptonote_format_utils.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "account"
diff --git a/src/cryptonote_core/account.h b/src/cryptonote_basic/account.h
index 41a119b07..b440adf33 100644
--- a/src/cryptonote_core/account.h
+++ b/src/cryptonote_basic/account.h
@@ -30,7 +30,7 @@
#pragma once
-#include "cryptonote_core/cryptonote_basic.h"
+#include "cryptonote_basic.h"
#include "crypto/crypto.h"
#include "serialization/keyvalue_serialization.h"
diff --git a/src/cryptonote_core/account_boost_serialization.h b/src/cryptonote_basic/account_boost_serialization.h
index 4151d9b50..ff5554b49 100644
--- a/src/cryptonote_core/account_boost_serialization.h
+++ b/src/cryptonote_basic/account_boost_serialization.h
@@ -31,7 +31,7 @@
#pragma once
#include "account.h"
-#include "cryptonote_core/cryptonote_boost_serialization.h"
+#include "cryptonote_boost_serialization.h"
//namespace cryptonote {
namespace boost
diff --git a/src/cryptonote_core/checkpoints.cpp b/src/cryptonote_basic/checkpoints.cpp
index 3cf804ede..3cf804ede 100644
--- a/src/cryptonote_core/checkpoints.cpp
+++ b/src/cryptonote_basic/checkpoints.cpp
diff --git a/src/cryptonote_core/checkpoints.h b/src/cryptonote_basic/checkpoints.h
index 71727753e..71727753e 100644
--- a/src/cryptonote_core/checkpoints.h
+++ b/src/cryptonote_basic/checkpoints.h
diff --git a/src/cryptonote_core/connection_context.h b/src/cryptonote_basic/connection_context.h
index 7e62e77b9..7e62e77b9 100644
--- a/src/cryptonote_core/connection_context.h
+++ b/src/cryptonote_basic/connection_context.h
diff --git a/src/cryptonote_core/cryptonote_basic.h b/src/cryptonote_basic/cryptonote_basic.h
index da069a21a..da069a21a 100644
--- a/src/cryptonote_core/cryptonote_basic.h
+++ b/src/cryptonote_basic/cryptonote_basic.h
diff --git a/src/cryptonote_core/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp
index 338210f01..338210f01 100644
--- a/src/cryptonote_core/cryptonote_basic_impl.cpp
+++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp
diff --git a/src/cryptonote_core/cryptonote_basic_impl.h b/src/cryptonote_basic/cryptonote_basic_impl.h
index 5703a7d75..5703a7d75 100644
--- a/src/cryptonote_core/cryptonote_basic_impl.h
+++ b/src/cryptonote_basic/cryptonote_basic_impl.h
diff --git a/src/cryptonote_core/cryptonote_boost_serialization.h b/src/cryptonote_basic/cryptonote_boost_serialization.h
index 409b9798c..409b9798c 100644
--- a/src/cryptonote_core/cryptonote_boost_serialization.h
+++ b/src/cryptonote_basic/cryptonote_boost_serialization.h
diff --git a/src/cryptonote_core/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp
index 2e6917878..2364663f3 100644
--- a/src/cryptonote_core/cryptonote_format_utils.cpp
+++ b/src/cryptonote_basic/cryptonote_format_utils.cpp
@@ -33,7 +33,6 @@ using namespace epee;
#include "cryptonote_format_utils.h"
#include "cryptonote_config.h"
-#include "miner.h"
#include "crypto/crypto.h"
#include "crypto/hash.h"
#include "ringct/rctSigs.h"
@@ -108,102 +107,6 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------
- bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) {
- tx.vin.clear();
- tx.vout.clear();
- tx.extra.clear();
-
- keypair txkey = keypair::generate();
- add_tx_pub_key_to_extra(tx, txkey.pub);
- if(!extra_nonce.empty())
- if(!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce))
- return false;
-
- txin_gen in;
- in.height = height;
-
- uint64_t block_reward;
- if(!get_block_reward(median_size, current_block_size, already_generated_coins, block_reward, hard_fork_version))
- {
- LOG_PRINT_L0("Block is too big");
- return false;
- }
-
-#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
- LOG_PRINT_L1("Creating block template: reward " << block_reward <<
- ", fee " << fee);
-#endif
- block_reward += fee;
-
- // from hard fork 2, we cut out the low significant digits. This makes the tx smaller, and
- // keeps the paid amount almost the same. The unpaid remainder gets pushed back to the
- // emission schedule
- // from hard fork 4, we use a single "dusty" output. This makes the tx even smaller,
- // and avoids the quantization. These outputs will be added as rct outputs with identity
- // masks, to they can be used as rct inputs.
- if (hard_fork_version >= 2 && hard_fork_version < 4) {
- block_reward = block_reward - block_reward % ::config::BASE_REWARD_CLAMP_THRESHOLD;
- }
-
- std::vector<uint64_t> out_amounts;
- decompose_amount_into_digits(block_reward, hard_fork_version >= 2 ? 0 : ::config::DEFAULT_DUST_THRESHOLD,
- [&out_amounts](uint64_t a_chunk) { out_amounts.push_back(a_chunk); },
- [&out_amounts](uint64_t a_dust) { out_amounts.push_back(a_dust); });
-
- CHECK_AND_ASSERT_MES(1 <= max_outs, false, "max_out must be non-zero");
- if (height == 0 || hard_fork_version >= 4)
- {
- // the genesis block was not decomposed, for unknown reasons
- while (max_outs < out_amounts.size())
- {
- //out_amounts[out_amounts.size() - 2] += out_amounts.back();
- //out_amounts.resize(out_amounts.size() - 1);
- out_amounts[1] += out_amounts[0];
- for (size_t n = 1; n < out_amounts.size(); ++n)
- out_amounts[n - 1] = out_amounts[n];
- out_amounts.resize(out_amounts.size() - 1);
- }
- }
- else
- {
- CHECK_AND_ASSERT_MES(max_outs >= out_amounts.size(), false, "max_out exceeded");
- }
-
- uint64_t summary_amounts = 0;
- for (size_t no = 0; no < out_amounts.size(); no++)
- {
- crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);;
- crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key);
- bool r = crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation);
- CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << miner_address.m_view_public_key << ", " << txkey.sec << ")");
-
- r = crypto::derive_public_key(derivation, no, miner_address.m_spend_public_key, out_eph_public_key);
- CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << no << ", "<< miner_address.m_spend_public_key << ")");
-
- txout_to_key tk;
- tk.key = out_eph_public_key;
-
- tx_out out;
- summary_amounts += out.amount = out_amounts[no];
- out.target = tk;
- tx.vout.push_back(out);
- }
-
- CHECK_AND_ASSERT_MES(summary_amounts == block_reward, false, "Failed to construct miner tx, summary_amounts = " << summary_amounts << " not equal block_reward = " << block_reward);
-
- if (hard_fork_version >= 4)
- tx.version = 2;
- else
- tx.version = 1;
-
- //lock
- tx.unlock_time = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
- tx.vin.push_back(in);
- //LOG_PRINT("MINER_TX generated ok, block_reward=" << print_money(block_reward) << "(" << print_money(block_reward - fee) << "+" << print_money(fee)
- // << "), current_block_size=" << current_block_size << ", already_generated_coins=" << already_generated_coins << ", tx_id=" << get_transaction_hash(tx), LOG_LEVEL_2);
- return true;
- }
- //---------------------------------------------------------------
bool generate_key_image_helper(const account_keys& ack, const crypto::public_key& tx_public_key, size_t real_output_index, keypair& in_ephemeral, crypto::key_image& ki)
{
crypto::key_derivation recv_derivation = AUTO_VAL_INIT(recv_derivation);
@@ -435,22 +338,6 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------
- crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const account_keys &sender_keys)
- {
- if (destinations.empty())
- return null_pkey;
- for (size_t n = 1; n < destinations.size(); ++n)
- {
- if (!memcmp(&destinations[n].addr, &sender_keys.m_account_address, sizeof(destinations[0].addr)))
- continue;
- if (destinations[n].amount == 0)
- continue;
- if (memcmp(&destinations[n].addr, &destinations[0].addr, sizeof(destinations[0].addr)))
- return null_pkey;
- }
- return destinations[0].addr.m_view_public_key;
- }
- //---------------------------------------------------------------
bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key)
{
crypto::key_derivation derivation;
@@ -475,313 +362,6 @@ namespace cryptonote
return encrypt_payment_id(payment_id, public_key, secret_key);
}
//---------------------------------------------------------------
- bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct)
- {
- std::vector<rct::key> amount_keys;
- tx.set_null();
- amount_keys.clear();
-
- tx.version = rct ? 2 : 1;
- tx.unlock_time = unlock_time;
-
- tx.extra = extra;
- keypair txkey = keypair::generate();
- remove_field_from_tx_extra(tx.extra, typeid(tx_extra_pub_key));
- add_tx_pub_key_to_extra(tx, txkey.pub);
- tx_key = txkey.sec;
-
- // if we have a stealth payment id, find it and encrypt it with the tx key now
- std::vector<tx_extra_field> tx_extra_fields;
- if (parse_tx_extra(tx.extra, tx_extra_fields))
- {
- tx_extra_nonce extra_nonce;
- if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce))
- {
- crypto::hash8 payment_id = null_hash8;
- if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
- {
- LOG_PRINT_L2("Encrypting payment id " << payment_id);
- crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, sender_account_keys);
- if (view_key_pub == null_pkey)
- {
- LOG_ERROR("Destinations have to have exactly one output to support encrypted payment ids");
- return false;
- }
-
- if (!encrypt_payment_id(payment_id, view_key_pub, txkey.sec))
- {
- LOG_ERROR("Failed to encrypt payment id");
- return false;
- }
-
- std::string extra_nonce;
- set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id);
- remove_field_from_tx_extra(tx.extra, typeid(tx_extra_nonce));
- if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce))
- {
- LOG_ERROR("Failed to add encrypted payment id to tx extra");
- return false;
- }
- LOG_PRINT_L1("Encrypted payment ID: " << payment_id);
- }
- }
- }
- else
- {
- LOG_ERROR("Failed to parse tx extra");
- return false;
- }
-
- struct input_generation_context_data
- {
- keypair in_ephemeral;
- };
- std::vector<input_generation_context_data> in_contexts;
-
- uint64_t summary_inputs_money = 0;
- //fill inputs
- int idx = -1;
- for(const tx_source_entry& src_entr: sources)
- {
- ++idx;
- if(src_entr.real_output >= src_entr.outputs.size())
- {
- LOG_ERROR("real_output index (" << src_entr.real_output << ")bigger than output_keys.size()=" << src_entr.outputs.size());
- return false;
- }
- summary_inputs_money += src_entr.amount;
-
- //key_derivation recv_derivation;
- in_contexts.push_back(input_generation_context_data());
- keypair& in_ephemeral = in_contexts.back().in_ephemeral;
- crypto::key_image img;
- if(!generate_key_image_helper(sender_account_keys, src_entr.real_out_tx_key, src_entr.real_output_in_tx_index, in_ephemeral, img))
- return false;
-
- //check that derivated key is equal with real output key
- if( !(in_ephemeral.pub == src_entr.outputs[src_entr.real_output].second.dest) )
- {
- LOG_ERROR("derived public key mismatch with output public key at index " << idx << ", real out " << src_entr.real_output << "! "<< ENDL << "derived_key:"
- << string_tools::pod_to_hex(in_ephemeral.pub) << ENDL << "real output_public_key:"
- << string_tools::pod_to_hex(src_entr.outputs[src_entr.real_output].second) );
- LOG_ERROR("amount " << src_entr.amount << ", rct " << src_entr.rct);
- LOG_ERROR("tx pubkey " << src_entr.real_out_tx_key << ", real_output_in_tx_index " << src_entr.real_output_in_tx_index);
- return false;
- }
-
- //put key image into tx input
- txin_to_key input_to_key;
- input_to_key.amount = src_entr.amount;
- input_to_key.k_image = img;
-
- //fill outputs array and use relative offsets
- for(const tx_source_entry::output_entry& out_entry: src_entr.outputs)
- input_to_key.key_offsets.push_back(out_entry.first);
-
- input_to_key.key_offsets = absolute_output_offsets_to_relative(input_to_key.key_offsets);
- tx.vin.push_back(input_to_key);
- }
-
- // "Shuffle" outs
- std::vector<tx_destination_entry> shuffled_dsts(destinations);
- std::sort(shuffled_dsts.begin(), shuffled_dsts.end(), [](const tx_destination_entry& de1, const tx_destination_entry& de2) { return de1.amount < de2.amount; } );
-
- uint64_t summary_outs_money = 0;
- //fill outputs
- size_t output_index = 0;
- for(const tx_destination_entry& dst_entr: shuffled_dsts)
- {
- CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version > 1, false, "Destination with wrong amount: " << dst_entr.amount);
- crypto::key_derivation derivation;
- crypto::public_key out_eph_public_key;
- bool r = crypto::generate_key_derivation(dst_entr.addr.m_view_public_key, txkey.sec, derivation);
- CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << txkey.sec << ")");
-
- if (tx.version > 1)
- {
- crypto::secret_key scalar1;
- crypto::derivation_to_scalar(derivation, output_index, scalar1);
- amount_keys.push_back(rct::sk2rct(scalar1));
- }
- r = crypto::derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key);
- CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << output_index << ", "<< dst_entr.addr.m_spend_public_key << ")");
-
- tx_out out;
- out.amount = dst_entr.amount;
- txout_to_key tk;
- tk.key = out_eph_public_key;
- out.target = tk;
- tx.vout.push_back(out);
- output_index++;
- summary_outs_money += dst_entr.amount;
- }
-
- //check money
- if(summary_outs_money > summary_inputs_money )
- {
- LOG_ERROR("Transaction inputs money ("<< summary_inputs_money << ") less than outputs money (" << summary_outs_money << ")");
- return false;
- }
-
- // check for watch only wallet
- bool zero_secret_key = true;
- for (size_t i = 0; i < sizeof(sender_account_keys.m_spend_secret_key); ++i)
- zero_secret_key &= (sender_account_keys.m_spend_secret_key.data[i] == 0);
- if (zero_secret_key)
- {
- MDEBUG("Null secret key, skipping signatures");
- }
-
- if (tx.version == 1)
- {
- //generate ring signatures
- crypto::hash tx_prefix_hash;
- get_transaction_prefix_hash(tx, tx_prefix_hash);
-
- std::stringstream ss_ring_s;
- size_t i = 0;
- for(const tx_source_entry& src_entr: sources)
- {
- ss_ring_s << "pub_keys:" << ENDL;
- std::vector<const crypto::public_key*> keys_ptrs;
- std::vector<crypto::public_key> keys(src_entr.outputs.size());
- size_t ii = 0;
- for(const tx_source_entry::output_entry& o: src_entr.outputs)
- {
- keys[ii] = rct2pk(o.second.dest);
- keys_ptrs.push_back(&keys[ii]);
- ss_ring_s << o.second.dest << ENDL;
- ++ii;
- }
-
- tx.signatures.push_back(std::vector<crypto::signature>());
- std::vector<crypto::signature>& sigs = tx.signatures.back();
- sigs.resize(src_entr.outputs.size());
- if (!zero_secret_key)
- crypto::generate_ring_signature(tx_prefix_hash, boost::get<txin_to_key>(tx.vin[i]).k_image, keys_ptrs, in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data());
- ss_ring_s << "signatures:" << ENDL;
- std::for_each(sigs.begin(), sigs.end(), [&](const crypto::signature& s){ss_ring_s << s << ENDL;});
- ss_ring_s << "prefix_hash:" << tx_prefix_hash << ENDL << "in_ephemeral_key: " << in_contexts[i].in_ephemeral.sec << ENDL << "real_output: " << src_entr.real_output;
- i++;
- }
-
- MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL << ss_ring_s.str());
- }
- else
- {
- size_t n_total_outs = sources[0].outputs.size(); // only for non-simple rct
-
- // the non-simple version is slightly smaller, but assumes all real inputs
- // are on the same index, so can only be used if there just one ring.
- bool use_simple_rct = sources.size() > 1;
-
- if (!use_simple_rct)
- {
- // non simple ringct requires all real inputs to be at the same index for all inputs
- for(const tx_source_entry& src_entr: sources)
- {
- if(src_entr.real_output != sources.begin()->real_output)
- {
- LOG_ERROR("All inputs must have the same index for non-simple ringct");
- return false;
- }
- }
-
- // enforce same mixin for all outputs
- for (size_t i = 1; i < sources.size(); ++i) {
- if (n_total_outs != sources[i].outputs.size()) {
- LOG_ERROR("Non-simple ringct transaction has varying mixin");
- return false;
- }
- }
- }
-
- uint64_t amount_in = 0, amount_out = 0;
- rct::ctkeyV inSk;
- // mixRing indexing is done the other way round for simple
- rct::ctkeyM mixRing(use_simple_rct ? sources.size() : n_total_outs);
- rct::keyV destinations;
- std::vector<uint64_t> inamounts, outamounts;
- std::vector<unsigned int> index;
- for (size_t i = 0; i < sources.size(); ++i)
- {
- rct::ctkey ctkey;
- amount_in += sources[i].amount;
- inamounts.push_back(sources[i].amount);
- index.push_back(sources[i].real_output);
- // inSk: (secret key, mask)
- ctkey.dest = rct::sk2rct(in_contexts[i].in_ephemeral.sec);
- ctkey.mask = sources[i].mask;
- inSk.push_back(ctkey);
- // inPk: (public key, commitment)
- // will be done when filling in mixRing
- }
- for (size_t i = 0; i < tx.vout.size(); ++i)
- {
- destinations.push_back(rct::pk2rct(boost::get<txout_to_key>(tx.vout[i].target).key));
- outamounts.push_back(tx.vout[i].amount);
- amount_out += tx.vout[i].amount;
- }
-
- if (use_simple_rct)
- {
- // mixRing indexing is done the other way round for simple
- for (size_t i = 0; i < sources.size(); ++i)
- {
- mixRing[i].resize(sources[i].outputs.size());
- for (size_t n = 0; n < sources[i].outputs.size(); ++n)
- {
- mixRing[i][n] = sources[i].outputs[n].second;
- }
- }
- }
- else
- {
- for (size_t i = 0; i < n_total_outs; ++i) // same index assumption
- {
- mixRing[i].resize(sources.size());
- for (size_t n = 0; n < sources.size(); ++n)
- {
- mixRing[i][n] = sources[n].outputs[i].second;
- }
- }
- }
-
- // fee
- if (!use_simple_rct && amount_in > amount_out)
- outamounts.push_back(amount_in - amount_out);
-
- // zero out all amounts to mask rct outputs, real amounts are now encrypted
- for (size_t i = 0; i < tx.vin.size(); ++i)
- {
- if (sources[i].rct)
- boost::get<txin_to_key>(tx.vin[i]).amount = 0;
- }
- for (size_t i = 0; i < tx.vout.size(); ++i)
- tx.vout[i].amount = 0;
-
- crypto::hash tx_prefix_hash;
- get_transaction_prefix_hash(tx, tx_prefix_hash);
- rct::ctkeyV outSk;
- if (use_simple_rct)
- tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, index, outSk);
- else
- tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, amount_keys, sources[0].real_output, outSk); // same index assumption
-
- CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout");
-
- MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL);
- }
-
- return true;
- }
- //---------------------------------------------------------------
- bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time)
- {
- crypto::secret_key tx_key;
- return construct_tx_and_get_tx_key(sender_account_keys, sources, destinations, extra, tx, unlock_time, tx_key);
- }
- //---------------------------------------------------------------
bool get_inputs_money_amount(const transaction& tx, uint64_t& money)
{
money = 0;
@@ -1057,36 +637,6 @@ namespace cryptonote
return p;
}
//---------------------------------------------------------------
- bool generate_genesis_block(
- block& bl
- , std::string const & genesis_tx
- , uint32_t nonce
- )
- {
- //genesis block
- bl = boost::value_initialized<block>();
-
-
- account_public_address ac = boost::value_initialized<account_public_address>();
- std::vector<size_t> sz;
- construct_miner_tx(0, 0, 0, 0, 0, ac, bl.miner_tx); // zero fee in genesis
- blobdata txb = tx_to_blob(bl.miner_tx);
- std::string hex_tx_represent = string_tools::buff_to_hex_nodelimer(txb);
-
- std::string genesis_coinbase_tx_hex = config::GENESIS_TX;
-
- blobdata tx_bl;
- string_tools::parse_hexstr_to_binbuff(genesis_coinbase_tx_hex, tx_bl);
- bool r = parse_and_validate_tx_from_blob(tx_bl, bl.miner_tx);
- CHECK_AND_ASSERT_MES(r, false, "failed to parse coinbase tx from hard coded blob");
- bl.major_version = CURRENT_BLOCK_MAJOR_VERSION;
- bl.minor_version = CURRENT_BLOCK_MINOR_VERSION;
- bl.timestamp = 0;
- bl.nonce = nonce;
- miner::find_nonce_for_given_block(bl, 1, 0);
- return true;
- }
- //---------------------------------------------------------------
bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height)
{
// block 202612 bug workaround
diff --git a/src/cryptonote_core/cryptonote_format_utils.h b/src/cryptonote_basic/cryptonote_format_utils.h
index a6610e60d..3ac456bb8 100644
--- a/src/cryptonote_core/cryptonote_format_utils.h
+++ b/src/cryptonote_basic/cryptonote_format_utils.h
@@ -30,14 +30,12 @@
#pragma once
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
-#include "cryptonote_core/cryptonote_basic_impl.h"
+#include "cryptonote_basic_impl.h"
#include "account.h"
#include "include_base_utils.h"
#include "crypto/crypto.h"
#include "crypto/hash.h"
#include "ringct/rctOps.h"
-#include <boost/serialization/vector.hpp>
-#include <boost/serialization/utility.hpp>
namespace cryptonote
{
@@ -46,43 +44,9 @@ namespace cryptonote
crypto::hash get_transaction_prefix_hash(const transaction_prefix& tx);
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx, crypto::hash& tx_hash, crypto::hash& tx_prefix_hash);
bool parse_and_validate_tx_from_blob(const blobdata& tx_blob, transaction& tx);
- bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1);
bool encrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key);
bool decrypt_payment_id(crypto::hash8 &payment_id, const crypto::public_key &public_key, const crypto::secret_key &secret_key);
- struct tx_source_entry
- {
- typedef std::pair<uint64_t, rct::ctkey> output_entry;
-
- std::vector<output_entry> outputs; //index + key + optional ringct commitment
- size_t real_output; //index in outputs vector of real output_entry
- crypto::public_key real_out_tx_key; //incoming real tx public key
- size_t real_output_in_tx_index; //index in transaction outputs vector
- uint64_t amount; //money
- bool rct; //true if the output is rct
- rct::key mask; //ringct amount mask
-
- void push_output(uint64_t idx, const crypto::public_key &k, uint64_t amount) { outputs.push_back(std::make_pair(idx, rct::ctkey({rct::pk2rct(k), rct::zeroCommit(amount)}))); }
- };
-
- struct tx_destination_entry
- {
- uint64_t amount; //money
- account_public_address addr; //destination address
-
- tx_destination_entry() : amount(0), addr(AUTO_VAL_INIT(addr)) { }
- tx_destination_entry(uint64_t a, const account_public_address &ad) : amount(a), addr(ad) { }
-
- BEGIN_SERIALIZE_OBJECT()
- VARINT_FIELD(amount)
- FIELD(addr)
- END_SERIALIZE()
- };
-
- //---------------------------------------------------------------
- bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time);
- bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct = false);
-
template<typename T>
bool find_tx_extra_field_by_type(const std::vector<tx_extra_field>& tx_extra_fields, T& field, size_t index = 0)
{
@@ -125,11 +89,6 @@ namespace cryptonote
crypto::hash get_block_hash(const block& b);
bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height);
crypto::hash get_block_longhash(const block& b, uint64_t height);
- bool generate_genesis_block(
- block& bl
- , std::string const & genesis_tx
- , uint32_t nonce
- );
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b);
bool get_inputs_money_amount(const transaction& tx, uint64_t& money);
uint64_t get_outs_money_amount(const transaction& tx);
@@ -252,23 +211,3 @@ namespace cryptonote
specific_type& variable_name = boost::get<specific_type>(variant_var);
}
-
-BOOST_CLASS_VERSION(cryptonote::tx_source_entry, 0)
-
-namespace boost
-{
- namespace serialization
- {
- template <class Archive>
- inline void serialize(Archive &a, cryptonote::tx_source_entry &x, const boost::serialization::version_type ver)
- {
- a & x.outputs;
- a & x.real_output;
- a & x.real_out_tx_key;
- a & x.real_output_in_tx_index;
- a & x.amount;
- a & x.rct;
- a & x.mask;
- }
- }
-}
diff --git a/src/cryptonote_core/cryptonote_stat_info.h b/src/cryptonote_basic/cryptonote_stat_info.h
index d44904b6d..d44904b6d 100644
--- a/src/cryptonote_core/cryptonote_stat_info.h
+++ b/src/cryptonote_basic/cryptonote_stat_info.h
diff --git a/src/cryptonote_core/difficulty.cpp b/src/cryptonote_basic/difficulty.cpp
index 1c5b9cfbd..1c5b9cfbd 100644
--- a/src/cryptonote_core/difficulty.cpp
+++ b/src/cryptonote_basic/difficulty.cpp
diff --git a/src/cryptonote_core/difficulty.h b/src/cryptonote_basic/difficulty.h
index 910f97035..910f97035 100644
--- a/src/cryptonote_core/difficulty.h
+++ b/src/cryptonote_basic/difficulty.h
diff --git a/src/cryptonote_core/hardfork.cpp b/src/cryptonote_basic/hardfork.cpp
index 13d7d717d..9b2434970 100644
--- a/src/cryptonote_core/hardfork.cpp
+++ b/src/cryptonote_basic/hardfork.cpp
@@ -29,7 +29,7 @@
#include <algorithm>
#include <cstdio>
-#include "cryptonote_core/cryptonote_basic.h"
+#include "cryptonote_basic.h"
#include "blockchain_db/blockchain_db.h"
#include "hardfork.h"
diff --git a/src/cryptonote_core/hardfork.h b/src/cryptonote_basic/hardfork.h
index 8d2edfa2a..a8ab32af7 100644
--- a/src/cryptonote_core/hardfork.h
+++ b/src/cryptonote_basic/hardfork.h
@@ -29,7 +29,7 @@
#pragma once
#include "syncobj.h"
-#include "cryptonote_core/cryptonote_basic.h"
+#include "cryptonote_basic.h"
namespace cryptonote
{
diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp
new file mode 100644
index 000000000..117c81878
--- /dev/null
+++ b/src/cryptonote_basic/miner.cpp
@@ -0,0 +1,807 @@
+// Copyright (c) 2014-2016, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#include <sstream>
+#include <numeric>
+#include <boost/utility/value_init.hpp>
+#include <boost/interprocess/detail/atomic.hpp>
+#include <boost/limits.hpp>
+#include "misc_language.h"
+#include "include_base_utils.h"
+#include "cryptonote_basic_impl.h"
+#include "cryptonote_format_utils.h"
+#include "file_io_utils.h"
+#include "common/command_line.h"
+#include "string_coding.h"
+#include "storages/portable_storage_template_helper.h"
+
+#undef MONERO_DEFAULT_LOG_CATEGORY
+#define MONERO_DEFAULT_LOG_CATEGORY "miner"
+
+using namespace epee;
+
+#include "miner.h"
+
+
+extern "C" void slow_hash_allocate_state();
+extern "C" void slow_hash_free_state();
+namespace cryptonote
+{
+
+ namespace
+ {
+ const command_line::arg_descriptor<std::string> arg_extra_messages = {"extra-messages-file", "Specify file for extra messages to include into coinbase transactions", "", true};
+ const command_line::arg_descriptor<std::string> arg_start_mining = {"start-mining", "Specify wallet address to mining for", "", true};
+ const command_line::arg_descriptor<uint32_t> arg_mining_threads = {"mining-threads", "Specify mining threads count", 0, true};
+ const command_line::arg_descriptor<bool> arg_bg_mining_enable = {"bg-mining-enable", "enable/disable background mining", true, true};
+ const command_line::arg_descriptor<uint64_t> arg_bg_mining_min_idle_interval_seconds = {"bg-mining-min-idle-interval", "Specify min lookback interval in seconds for determining idle state", miner::BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS, true};
+ const command_line::arg_descriptor<uint8_t> arg_bg_mining_idle_threshold_percentage = {"bg-mining-idle-threshold", "Specify minimum avg idle percentage over lookback interval", miner::BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE, true};
+ const command_line::arg_descriptor<uint8_t> arg_bg_mining_miner_target_percentage = {"bg-mining-miner-target", "Specificy maximum percentage cpu use by miner(s)", miner::BACKGROUND_MINING_DEFAULT_MINING_TARGET_PERCENTAGE, true};
+ }
+
+
+ miner::miner(i_miner_handler* phandler):m_stop(1),
+ m_template(boost::value_initialized<block>()),
+ m_template_no(0),
+ m_diffic(0),
+ m_thread_index(0),
+ m_phandler(phandler),
+ m_height(0),
+ m_pausers_count(0),
+ m_threads_total(0),
+ m_starter_nonce(0),
+ m_last_hr_merge_time(0),
+ m_hashes(0),
+ m_do_print_hashrate(false),
+ m_do_mining(false),
+ m_current_hash_rate(0),
+ m_is_background_mining_enabled(false),
+ m_min_idle_seconds(BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS),
+ m_idle_threshold(BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE),
+ m_mining_target(BACKGROUND_MINING_DEFAULT_MINING_TARGET_PERCENTAGE),
+ m_miner_extra_sleep(BACKGROUND_MINING_DEFAULT_MINER_EXTRA_SLEEP_MILLIS)
+ {
+
+ }
+ //-----------------------------------------------------------------------------------------------------
+ miner::~miner()
+ {
+ stop();
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::set_block_template(const block& bl, const difficulty_type& di, uint64_t height)
+ {
+ CRITICAL_REGION_LOCAL(m_template_lock);
+ m_template = bl;
+ m_diffic = di;
+ m_height = height;
+ ++m_template_no;
+ m_starter_nonce = crypto::rand<uint32_t>();
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::on_block_chain_update()
+ {
+ if(!is_mining())
+ return true;
+
+ return request_block_template();
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::request_block_template()
+ {
+ block bl = AUTO_VAL_INIT(bl);
+ difficulty_type di = AUTO_VAL_INIT(di);
+ uint64_t height = AUTO_VAL_INIT(height);
+ cryptonote::blobdata extra_nonce;
+ if(m_extra_messages.size() && m_config.current_extra_message_index < m_extra_messages.size())
+ {
+ extra_nonce = m_extra_messages[m_config.current_extra_message_index];
+ }
+
+ if(!m_phandler->get_block_template(bl, m_mine_address, di, height, extra_nonce))
+ {
+ LOG_ERROR("Failed to get_block_template(), stopping mining");
+ return false;
+ }
+ set_block_template(bl, di, height);
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::on_idle()
+ {
+ m_update_block_template_interval.do_call([&](){
+ if(is_mining())request_block_template();
+ return true;
+ });
+
+ m_update_merge_hr_interval.do_call([&](){
+ merge_hr();
+ return true;
+ });
+
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ void miner::do_print_hashrate(bool do_hr)
+ {
+ m_do_print_hashrate = do_hr;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ void miner::merge_hr()
+ {
+ if(m_last_hr_merge_time && is_mining())
+ {
+ m_current_hash_rate = m_hashes * 1000 / ((misc_utils::get_tick_count() - m_last_hr_merge_time + 1));
+ CRITICAL_REGION_LOCAL(m_last_hash_rates_lock);
+ m_last_hash_rates.push_back(m_current_hash_rate);
+ if(m_last_hash_rates.size() > 19)
+ m_last_hash_rates.pop_front();
+ if(m_do_print_hashrate)
+ {
+ uint64_t total_hr = std::accumulate(m_last_hash_rates.begin(), m_last_hash_rates.end(), 0);
+ float hr = static_cast<float>(total_hr)/static_cast<float>(m_last_hash_rates.size());
+ std::cout << "hashrate: " << std::setprecision(4) << std::fixed << hr << ENDL;
+ }
+ }
+ m_last_hr_merge_time = misc_utils::get_tick_count();
+ m_hashes = 0;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ void miner::init_options(boost::program_options::options_description& desc)
+ {
+ command_line::add_arg(desc, arg_extra_messages);
+ command_line::add_arg(desc, arg_start_mining);
+ command_line::add_arg(desc, arg_mining_threads);
+ command_line::add_arg(desc, arg_bg_mining_enable);
+ command_line::add_arg(desc, arg_bg_mining_min_idle_interval_seconds);
+ command_line::add_arg(desc, arg_bg_mining_idle_threshold_percentage);
+ command_line::add_arg(desc, arg_bg_mining_miner_target_percentage);
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::init(const boost::program_options::variables_map& vm, bool testnet)
+ {
+ if(command_line::has_arg(vm, arg_extra_messages))
+ {
+ std::string buff;
+ bool r = file_io_utils::load_file_to_string(command_line::get_arg(vm, arg_extra_messages), buff);
+ CHECK_AND_ASSERT_MES(r, false, "Failed to load file with extra messages: " << command_line::get_arg(vm, arg_extra_messages));
+ std::vector<std::string> extra_vec;
+ boost::split(extra_vec, buff, boost::is_any_of("\n"), boost::token_compress_on );
+ m_extra_messages.resize(extra_vec.size());
+ for(size_t i = 0; i != extra_vec.size(); i++)
+ {
+ string_tools::trim(extra_vec[i]);
+ if(!extra_vec[i].size())
+ continue;
+ std::string buff = string_encoding::base64_decode(extra_vec[i]);
+ if(buff != "0")
+ m_extra_messages[i] = buff;
+ }
+ m_config_folder_path = boost::filesystem::path(command_line::get_arg(vm, arg_extra_messages)).parent_path().string();
+ m_config = AUTO_VAL_INIT(m_config);
+ epee::serialization::load_t_from_json_file(m_config, m_config_folder_path + "/" + MINER_CONFIG_FILE_NAME);
+ MINFO("Loaded " << m_extra_messages.size() << " extra messages, current index " << m_config.current_extra_message_index);
+ }
+
+ if(command_line::has_arg(vm, arg_start_mining))
+ {
+ if(!cryptonote::get_account_address_from_str(m_mine_address, testnet, command_line::get_arg(vm, arg_start_mining)))
+ {
+ LOG_ERROR("Target account address " << command_line::get_arg(vm, arg_start_mining) << " has wrong format, starting daemon canceled");
+ return false;
+ }
+ m_threads_total = 1;
+ m_do_mining = true;
+ if(command_line::has_arg(vm, arg_mining_threads))
+ {
+ m_threads_total = command_line::get_arg(vm, arg_mining_threads);
+ }
+ }
+
+ // Background mining parameters
+ // Let init set all parameters even if background mining is not enabled, they can start later with params set
+ if(command_line::has_arg(vm, arg_bg_mining_enable))
+ set_is_background_mining_enabled( command_line::get_arg(vm, arg_bg_mining_enable) );
+ if(command_line::has_arg(vm, arg_bg_mining_min_idle_interval_seconds))
+ set_min_idle_seconds( command_line::get_arg(vm, arg_bg_mining_min_idle_interval_seconds) );
+ if(command_line::has_arg(vm, arg_bg_mining_idle_threshold_percentage))
+ set_idle_threshold( command_line::get_arg(vm, arg_bg_mining_idle_threshold_percentage) );
+ if(command_line::has_arg(vm, arg_bg_mining_miner_target_percentage))
+ set_mining_target( command_line::get_arg(vm, arg_bg_mining_miner_target_percentage) );
+
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::is_mining() const
+ {
+ 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 do_background)
+ {
+ m_mine_address = adr;
+ m_threads_total = static_cast<uint32_t>(threads_count);
+ m_starter_nonce = crypto::rand<uint32_t>();
+ CRITICAL_REGION_LOCAL(m_threads_lock);
+ if(is_mining())
+ {
+ LOG_ERROR("Starting miner but it's already started");
+ return false;
+ }
+
+ if(!m_threads.empty())
+ {
+ LOG_ERROR("Unable to start miner because there are active mining threads");
+ return false;
+ }
+
+ if(!m_template_no)
+ request_block_template();//lets update block template
+
+ boost::interprocess::ipcdetail::atomic_write32(&m_stop, 0);
+ boost::interprocess::ipcdetail::atomic_write32(&m_thread_index, 0);
+ set_is_background_mining_enabled(do_background);
+
+ for(size_t i = 0; i != threads_count; i++)
+ {
+ m_threads.push_back(boost::thread(attrs, boost::bind(&miner::worker_thread, this)));
+ }
+
+ LOG_PRINT_L0("Mining has started with " << threads_count << " threads, good luck!" );
+
+ if( get_is_background_mining_enabled() )
+ {
+ m_background_mining_thread = boost::thread(attrs, boost::bind(&miner::background_worker_thread, this));
+ LOG_PRINT_L0("Background mining controller thread started" );
+ }
+
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ uint64_t miner::get_speed() const
+ {
+ if(is_mining()) {
+ return m_current_hash_rate;
+ }
+ else {
+ return 0;
+ }
+ }
+ //-----------------------------------------------------------------------------------------------------
+ void miner::send_stop_signal()
+ {
+ boost::interprocess::ipcdetail::atomic_write32(&m_stop, 1);
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::stop()
+ {
+ MTRACE("Miner has received stop signal");
+
+ if (!is_mining())
+ {
+ MDEBUG("Not mining - nothing to stop" );
+ return true;
+ }
+
+ send_stop_signal();
+ CRITICAL_REGION_LOCAL(m_threads_lock);
+
+ // In case background mining was active and the miner threads are waiting
+ // on the background miner to signal start.
+ m_is_background_mining_started_cond.notify_all();
+
+ for(boost::thread& th: m_threads)
+ th.join();
+
+ // The background mining thread could be sleeping for a long time, so we
+ // interrupt it just in case
+ m_background_mining_thread.interrupt();
+ m_background_mining_thread.join();
+
+ MINFO("Mining has been stopped, " << m_threads.size() << " finished" );
+ m_threads.clear();
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::find_nonce_for_given_block(block& bl, const difficulty_type& diffic, uint64_t height)
+ {
+ for(; bl.nonce != std::numeric_limits<uint32_t>::max(); bl.nonce++)
+ {
+ crypto::hash h;
+ get_block_longhash(bl, h, height);
+
+ if(check_hash(h, diffic))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ void miner::on_synchronized()
+ {
+ if(m_do_mining)
+ {
+ boost::thread::attributes attrs;
+ attrs.set_stack_size(THREAD_STACK_SIZE);
+
+ start(m_mine_address, m_threads_total, attrs, get_is_background_mining_enabled());
+ }
+ }
+ //-----------------------------------------------------------------------------------------------------
+ void miner::pause()
+ {
+ CRITICAL_REGION_LOCAL(m_miners_count_lock);
+ ++m_pausers_count;
+ if(m_pausers_count == 1 && is_mining())
+ MDEBUG("MINING PAUSED");
+ }
+ //-----------------------------------------------------------------------------------------------------
+ void miner::resume()
+ {
+ CRITICAL_REGION_LOCAL(m_miners_count_lock);
+ --m_pausers_count;
+ if(m_pausers_count < 0)
+ {
+ m_pausers_count = 0;
+ MERROR("Unexpected miner::resume() called");
+ }
+ if(!m_pausers_count && is_mining())
+ MDEBUG("MINING RESUMED");
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::worker_thread()
+ {
+ uint32_t th_local_index = boost::interprocess::ipcdetail::atomic_inc32(&m_thread_index);
+ MGINFO("Miner thread was started ["<< th_local_index << "]");
+ MLOG_SET_THREAD_NAME(std::string("[miner ") + std::to_string(th_local_index) + "]");
+ uint32_t nonce = m_starter_nonce + th_local_index;
+ uint64_t height = 0;
+ difficulty_type local_diff = 0;
+ uint32_t local_template_ver = 0;
+ block b;
+ slow_hash_allocate_state();
+ while(!m_stop)
+ {
+ if(m_pausers_count)//anti split workaround
+ {
+ misc_utils::sleep_no_w(100);
+ continue;
+ }
+ else if( m_is_background_mining_enabled )
+ {
+ misc_utils::sleep_no_w(m_miner_extra_sleep);
+ while( !m_is_background_mining_started )
+ {
+ MGINFO("background mining is enabled, but not started, waiting until start triggers");
+ boost::unique_lock<boost::mutex> started_lock( m_is_background_mining_started_mutex );
+ m_is_background_mining_started_cond.wait( started_lock );
+ if( m_stop ) break;
+ }
+
+ if( m_stop ) continue;
+ }
+
+ if(local_template_ver != m_template_no)
+ {
+ CRITICAL_REGION_BEGIN(m_template_lock);
+ b = m_template;
+ local_diff = m_diffic;
+ height = m_height;
+ CRITICAL_REGION_END();
+ local_template_ver = m_template_no;
+ nonce = m_starter_nonce + th_local_index;
+ }
+
+ if(!local_template_ver)//no any set_block_template call
+ {
+ LOG_PRINT_L2("Block template not set yet");
+ epee::misc_utils::sleep_no_w(1000);
+ continue;
+ }
+
+ b.nonce = nonce;
+ crypto::hash h;
+ get_block_longhash(b, h, height);
+
+ if(check_hash(h, local_diff))
+ {
+ //we lucky!
+ ++m_config.current_extra_message_index;
+ MGINFO_GREEN("Found block for difficulty: " << local_diff);
+ if(!m_phandler->handle_block_found(b))
+ {
+ --m_config.current_extra_message_index;
+ }else
+ {
+ //success update, lets update config
+ if (!m_config_folder_path.empty())
+ epee::serialization::store_t_to_json_file(m_config, m_config_folder_path + "/" + MINER_CONFIG_FILE_NAME);
+ }
+ }
+ nonce+=m_threads_total;
+ ++m_hashes;
+ }
+ slow_hash_free_state();
+ MGINFO("Miner thread stopped ["<< th_local_index << "]");
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::get_is_background_mining_enabled() const
+ {
+ return m_is_background_mining_enabled;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ /**
+ * This has differing behaviour depending on if mining has been started/etc.
+ * Note: add documentation
+ */
+ bool miner::set_is_background_mining_enabled(bool is_background_mining_enabled)
+ {
+ m_is_background_mining_enabled = is_background_mining_enabled;
+ // Extra logic will be required if we make this function public in the future
+ // and allow toggling smart mining without start/stop
+ //m_is_background_mining_enabled_cond.notify_one();
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ uint64_t miner::get_min_idle_seconds() const
+ {
+ return m_min_idle_seconds;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::set_min_idle_seconds(uint64_t min_idle_seconds)
+ {
+ if(min_idle_seconds > BACKGROUND_MINING_MAX_MIN_IDLE_INTERVAL_IN_SECONDS) return false;
+ if(min_idle_seconds < BACKGROUND_MINING_MIN_MIN_IDLE_INTERVAL_IN_SECONDS) return false;
+ m_min_idle_seconds = min_idle_seconds;
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ uint8_t miner::get_idle_threshold() const
+ {
+ return m_idle_threshold;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::set_idle_threshold(uint8_t idle_threshold)
+ {
+ if(idle_threshold > BACKGROUND_MINING_MAX_IDLE_THRESHOLD_PERCENTAGE) return false;
+ if(idle_threshold < BACKGROUND_MINING_MIN_IDLE_THRESHOLD_PERCENTAGE) return false;
+ m_idle_threshold = idle_threshold;
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ uint8_t miner::get_mining_target() const
+ {
+ return m_mining_target;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::set_mining_target(uint8_t mining_target)
+ {
+ if(mining_target > BACKGROUND_MINING_MAX_MINING_TARGET_PERCENTAGE) return false;
+ if(mining_target < BACKGROUND_MINING_MIN_MINING_TARGET_PERCENTAGE) return false;
+ m_mining_target = mining_target;
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::background_worker_thread()
+ {
+ uint64_t prev_total_time, current_total_time;
+ uint64_t prev_idle_time, current_idle_time;
+ uint64_t previous_process_time = 0, current_process_time = 0;
+ m_is_background_mining_started = false;
+
+ if(!get_system_times(prev_total_time, prev_idle_time))
+ {
+ LOG_ERROR("get_system_times call failed, background mining will NOT work!");
+ return false;
+ }
+
+ while(!m_stop)
+ {
+
+ try
+ {
+ // Commenting out the below since we're going with privatizing the bg mining enabled
+ // function, but I'll leave the code/comments here for anyone that wants to modify the
+ // patch in the future
+ // -------------------------------------------------------------------------------------
+ // All of this might be overkill if we just enforced some simple requirements
+ // about changing this variable before/after the miner starts, but I envision
+ // in the future a checkbox that you can tick on/off for background mining after
+ // you've clicked "start mining". There's still an issue here where if background
+ // mining is disabled when start is called, this thread is never created, and so
+ // enabling after does nothing, something I have to fix in the future. However,
+ // this should take care of the case where mining is started with bg-enabled,
+ // and then the user decides to un-check background mining, and just do
+ // regular full-speed mining. I might just be over-doing it and thinking up
+ // non-existant use-cases, so if the concensus is to simplify, we can remove all this fluff.
+ /*
+ while( !m_is_background_mining_enabled )
+ {
+ MGINFO("background mining is disabled, waiting until enabled!");
+ boost::unique_lock<boost::mutex> enabled_lock( m_is_background_mining_enabled_mutex );
+ m_is_background_mining_enabled_cond.wait( enabled_lock );
+ }
+ */
+
+ // If we're already mining, then sleep for the miner monitor interval.
+ // If we're NOT mining, then sleep for the idle monitor interval
+ boost::this_thread::sleep_for(
+ m_is_background_mining_started ?
+ boost::chrono::seconds( BACKGROUND_MINING_MINER_MONITOR_INVERVAL_IN_SECONDS ) :
+ boost::chrono::seconds( get_min_idle_seconds() ) );
+ }
+ catch(const boost::thread_interrupted&)
+ {
+ MDEBUG("background miner thread interrupted ");
+ continue; // if interrupted because stop called, loop should end ..
+ }
+
+ bool on_ac_power = !on_battery_power();
+
+ if( m_is_background_mining_started )
+ {
+ // figure out if we need to stop, and monitor mining usage
+
+ // If we get here, then previous values are initialized.
+ // Let's get some current data for comparison.
+
+ if(!get_system_times(current_total_time, current_idle_time))
+ {
+ MERROR("get_system_times call failed");
+ continue;
+ }
+
+ if(!get_process_time(current_process_time))
+ {
+ MERROR("get_process_time call failed!");
+ continue;
+ }
+
+ uint64_t total_diff = (current_total_time - prev_total_time);
+ uint64_t idle_diff = (current_idle_time - prev_idle_time);
+ uint64_t process_diff = (current_process_time - previous_process_time);
+ uint8_t idle_percentage = get_percent_of_total(idle_diff, total_diff);
+ uint8_t process_percentage = get_percent_of_total(process_diff, total_diff);
+
+ MGINFO("idle percentage is " << unsigned(idle_percentage) << "\%, miner percentage is " << unsigned(process_percentage) << "\%, ac power : " << on_ac_power);
+ if( idle_percentage + process_percentage < get_idle_threshold() || !on_ac_power )
+ {
+ MGINFO("cpu is " << unsigned(idle_percentage) << "% idle, idle threshold is " << unsigned(get_idle_threshold()) << "\%, ac power : " << on_ac_power << ", background mining stopping, thanks for your contribution!");
+ m_is_background_mining_started = false;
+
+ // reset process times
+ previous_process_time = 0;
+ current_process_time = 0;
+ }
+ else
+ {
+ previous_process_time = current_process_time;
+
+ // adjust the miner extra sleep variable
+ int64_t miner_extra_sleep_change = (-1 * (get_mining_target() - process_percentage) );
+ int64_t new_miner_extra_sleep = m_miner_extra_sleep + miner_extra_sleep_change;
+ // if you start the miner with few threads on a multicore system, this could
+ // fall below zero because all the time functions aggregate across all processors.
+ // I'm just hard limiting to 5 millis min sleep here, other options?
+ m_miner_extra_sleep = std::max( new_miner_extra_sleep , (int64_t)5 );
+ MDEBUG("m_miner_extra_sleep " << m_miner_extra_sleep);
+ }
+
+ prev_total_time = current_total_time;
+ prev_idle_time = current_idle_time;
+ }
+ else if( on_ac_power )
+ {
+ // figure out if we need to start
+
+ if(!get_system_times(current_total_time, current_idle_time))
+ {
+ MERROR("get_system_times call failed");
+ continue;
+ }
+
+ uint64_t total_diff = (current_total_time - prev_total_time);
+ uint64_t idle_diff = (current_idle_time - prev_idle_time);
+ uint8_t idle_percentage = get_percent_of_total(idle_diff, total_diff);
+
+ MGINFO("idle percentage is " << unsigned(idle_percentage));
+ if( idle_percentage >= get_idle_threshold() && on_ac_power )
+ {
+ MGINFO("cpu is " << unsigned(idle_percentage) << "% idle, idle threshold is " << unsigned(get_idle_threshold()) << "\%, ac power : " << on_ac_power << ", background mining started, good luck!");
+ m_is_background_mining_started = true;
+ m_is_background_mining_started_cond.notify_all();
+
+ // Wait for a little mining to happen ..
+ boost::this_thread::sleep_for(boost::chrono::seconds( 1 ));
+
+ // Starting data ...
+ if(!get_process_time(previous_process_time))
+ {
+ m_is_background_mining_started = false;
+ MERROR("get_process_time call failed!");
+ }
+ }
+
+ prev_total_time = current_total_time;
+ prev_idle_time = current_idle_time;
+ }
+ }
+
+ return true;
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::get_system_times(uint64_t& total_time, uint64_t& idle_time)
+ {
+ #ifdef _WIN32
+
+ FILETIME idleTime;
+ FILETIME kernelTime;
+ FILETIME userTime;
+ if ( GetSystemTimes( &idleTime, &kernelTime, &userTime ) != -1 )
+ {
+ total_time =
+ ( (((uint64_t)(kernelTime.dwHighDateTime)) << 32) | ((uint64_t)kernelTime.dwLowDateTime) )
+ + ( (((uint64_t)(userTime.dwHighDateTime)) << 32) | ((uint64_t)userTime.dwLowDateTime) );
+
+ idle_time = ( (((uint64_t)(idleTime.dwHighDateTime)) << 32) | ((uint64_t)idleTime.dwLowDateTime) );
+
+ return true;
+ }
+
+ #elif defined(__linux__)
+
+ const std::string STR_CPU("cpu");
+ const std::size_t STR_CPU_LEN = STR_CPU.size();
+ const std::string STAT_FILE_PATH = "/proc/stat";
+
+ if( !epee::file_io_utils::is_file_exist(STAT_FILE_PATH) )
+ {
+ LOG_ERROR("'" << STAT_FILE_PATH << "' file does not exist");
+ return false;
+ }
+
+ std::ifstream stat_file_stream(STAT_FILE_PATH);
+ if( stat_file_stream.fail() )
+ {
+ LOG_ERROR("failed to open '" << STAT_FILE_PATH << "'");
+ return false;
+ }
+
+ std::string line;
+ std::getline(stat_file_stream, line);
+ std::istringstream stat_file_iss(line);
+ stat_file_iss.ignore(65536, ' '); // skip cpu label ...
+ uint64_t utime, ntime, stime, itime;
+ if( !(stat_file_iss >> utime && stat_file_iss >> ntime && stat_file_iss >> stime && stat_file_iss >> itime) )
+ {
+ LOG_ERROR("failed to read '" << STAT_FILE_PATH << "'");
+ return false;
+ }
+
+ idle_time = itime;
+ total_time = utime + ntime + stime + itime;
+
+ return true;
+
+ #endif
+
+ return false; // unsupported systemm..
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::get_process_time(uint64_t& total_time)
+ {
+ #ifdef _WIN32
+
+ FILETIME createTime;
+ FILETIME exitTime;
+ FILETIME kernelTime;
+ FILETIME userTime;
+ if ( GetProcessTimes( GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime ) != -1 )
+ {
+ total_time =
+ ( (((uint64_t)(kernelTime.dwHighDateTime)) << 32) | ((uint64_t)kernelTime.dwLowDateTime) )
+ + ( (((uint64_t)(userTime.dwHighDateTime)) << 32) | ((uint64_t)userTime.dwLowDateTime) );
+
+ return true;
+ }
+
+ #elif defined(__linux__) && defined(_SC_CLK_TCK)
+
+ struct tms tms;
+ if ( times(&tms) != (clock_t)-1 )
+ {
+ total_time = tms.tms_utime + tms.tms_stime;
+ return true;
+ }
+
+ #endif
+
+ return false; // unsupported system..
+ }
+ //-----------------------------------------------------------------------------------------------------
+ uint8_t miner::get_percent_of_total(uint64_t other, uint64_t total)
+ {
+ return (uint8_t)( ceil( (other * 1.f / total * 1.f) * 100) );
+ }
+ //-----------------------------------------------------------------------------------------------------
+ bool miner::on_battery_power()
+ {
+ #ifdef _WIN32
+
+ SYSTEM_POWER_STATUS power_status;
+ if ( GetSystemPowerStatus( &power_status ) != 0 )
+ {
+ return power_status.ACLineStatus != 1;
+ }
+
+ #elif defined(__linux__)
+
+ // i've only tested on UBUNTU, these paths might be different on other systems
+ // need to figure out a way to make this more flexible
+ const std::string POWER_SUPPLY_STATUS_PATH = "/sys/class/power_supply/ACAD/online";
+
+ if( !epee::file_io_utils::is_file_exist(POWER_SUPPLY_STATUS_PATH) )
+ {
+ LOG_ERROR("'" << POWER_SUPPLY_STATUS_PATH << "' file does not exist, can't determine if on AC power");
+ return false;
+ }
+
+ std::ifstream power_stream(POWER_SUPPLY_STATUS_PATH);
+ if( power_stream.fail() )
+ {
+ LOG_ERROR("failed to open '" << POWER_SUPPLY_STATUS_PATH << "'");
+ return false;
+ }
+
+ return power_stream.get() != '1';
+
+ #endif
+
+ LOG_ERROR("couldn't query power status");
+ return false; // shouldn't get here unless no support for querying battery status
+ // TODO: return enum with ability to signify failure in querying for power status
+ // and change bg-mining logic so that it stops. As @vtnerd states, with the current
+ // setup "If someone enabled background mining on a system that fails to grab ac
+ // status, it will just continually check with little hope of ever being resolved
+ // automagically". This is also the case for time/idle stats functions.
+ }
+}
diff --git a/src/cryptonote_core/miner.h b/src/cryptonote_basic/miner.h
index f24f6e960..a66083ead 100644
--- a/src/cryptonote_core/miner.h
+++ b/src/cryptonote_basic/miner.h
@@ -35,7 +35,14 @@
#include "cryptonote_basic.h"
#include "difficulty.h"
#include "math_helper.h"
-
+#ifdef _WIN32
+#include <windows.h>
+#elif defined(__linux__)
+#include <unistd.h>
+#include <sys/resource.h>
+#include <sys/times.h>
+#include <time.h>
+#endif
namespace cryptonote
{
@@ -60,7 +67,7 @@ namespace cryptonote
static void init_options(boost::program_options::options_description& desc);
bool set_block_template(const block& bl, const difficulty_type& diffic, uint64_t height);
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, bool do_background = false);
uint64_t get_speed() const;
uint32_t get_threads_count() const;
void send_stop_signal();
@@ -74,6 +81,26 @@ namespace cryptonote
void pause();
void resume();
void do_print_hashrate(bool do_hr);
+ bool get_is_background_mining_enabled() const;
+ uint64_t get_min_idle_seconds() const;
+ bool set_min_idle_seconds(uint64_t min_idle_seconds);
+ uint8_t get_idle_threshold() const;
+ bool set_idle_threshold(uint8_t idle_threshold);
+ uint8_t get_mining_target() const;
+ bool set_mining_target(uint8_t mining_target);
+
+ static constexpr uint8_t BACKGROUND_MINING_DEFAULT_IDLE_THRESHOLD_PERCENTAGE = 90;
+ static constexpr uint8_t BACKGROUND_MINING_MIN_IDLE_THRESHOLD_PERCENTAGE = 50;
+ static constexpr uint8_t BACKGROUND_MINING_MAX_IDLE_THRESHOLD_PERCENTAGE = 99;
+ static constexpr uint16_t BACKGROUND_MINING_DEFAULT_MIN_IDLE_INTERVAL_IN_SECONDS = 10;
+ static constexpr uint16_t BACKGROUND_MINING_MIN_MIN_IDLE_INTERVAL_IN_SECONDS = 10;
+ static constexpr uint16_t BACKGROUND_MINING_MAX_MIN_IDLE_INTERVAL_IN_SECONDS = 3600;
+ static constexpr uint8_t BACKGROUND_MINING_DEFAULT_MINING_TARGET_PERCENTAGE = 40;
+ static constexpr uint8_t BACKGROUND_MINING_MIN_MINING_TARGET_PERCENTAGE = 5;
+ static constexpr uint8_t BACKGROUND_MINING_MAX_MINING_TARGET_PERCENTAGE = 50;
+ static constexpr uint8_t BACKGROUND_MINING_MINER_MONITOR_INVERVAL_IN_SECONDS = 10;
+ static constexpr uint64_t BACKGROUND_MINING_DEFAULT_MINER_EXTRA_SLEEP_MILLIS = 400; // ramp up
+ static constexpr uint64_t BACKGROUND_MINING_MIN_MINER_EXTRA_SLEEP_MILLIS = 5;
private:
bool worker_thread();
@@ -119,8 +146,24 @@ namespace cryptonote
bool m_do_print_hashrate;
bool m_do_mining;
+ // background mining stuffs ..
+
+ bool set_is_background_mining_enabled(bool is_background_mining_enabled);
+ bool background_worker_thread();
+ std::atomic<bool> m_is_background_mining_enabled;
+ boost::mutex m_is_background_mining_enabled_mutex;
+ boost::condition_variable m_is_background_mining_enabled_cond;
+ std::atomic<bool> m_is_background_mining_started;
+ boost::mutex m_is_background_mining_started_mutex;
+ boost::condition_variable m_is_background_mining_started_cond;
+ boost::thread m_background_mining_thread;
+ uint64_t m_min_idle_seconds;
+ uint8_t m_idle_threshold;
+ uint8_t m_mining_target;
+ std::atomic<uint64_t> m_miner_extra_sleep;
+ static bool get_system_times(uint64_t& total_time, uint64_t& idle_time);
+ static bool get_process_time(uint64_t& total_time);
+ static uint8_t get_percent_of_total(uint64_t some_time, uint64_t total_time);
+ static bool on_battery_power();
};
}
-
-
-
diff --git a/src/cryptonote_core/tx_extra.h b/src/cryptonote_basic/tx_extra.h
index 6f5fbe466..6f5fbe466 100644
--- a/src/cryptonote_core/tx_extra.h
+++ b/src/cryptonote_basic/tx_extra.h
diff --git a/src/cryptonote_core/verification_context.h b/src/cryptonote_basic/verification_context.h
index 0bb635e84..0bb635e84 100644
--- a/src/cryptonote_core/verification_context.h
+++ b/src/cryptonote_basic/verification_context.h
diff --git a/src/cryptonote_core/CMakeLists.txt b/src/cryptonote_core/CMakeLists.txt
index ad1745b7f..a5f25041b 100644
--- a/src/cryptonote_core/CMakeLists.txt
+++ b/src/cryptonote_core/CMakeLists.txt
@@ -27,38 +27,19 @@
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set(cryptonote_core_sources
- account.cpp
blockchain.cpp
- checkpoints.cpp
- cryptonote_basic_impl.cpp
cryptonote_core.cpp
- cryptonote_format_utils.cpp
- difficulty.cpp
- miner.cpp
tx_pool.cpp
- hardfork.cpp)
+ cryptonote_tx_utils.cpp)
set(cryptonote_core_headers)
set(cryptonote_core_private_headers
- account.h
- account_boost_serialization.h
blockchain_storage_boost_serialization.h
blockchain.h
- checkpoints.h
- connection_context.h
- cryptonote_basic.h
- cryptonote_basic_impl.h
- cryptonote_boost_serialization.h
cryptonote_core.h
- cryptonote_format_utils.h
- cryptonote_stat_info.h
- difficulty.h
- miner.h
- tx_extra.h
tx_pool.h
- verification_context.h
- hardfork.h)
+ cryptonote_tx_utils.h)
if(PER_BLOCK_CHECKPOINT)
set(Blocks "blocks")
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index b344c5597..a81286632 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -34,14 +34,13 @@
#include <boost/range/adaptor/reversed.hpp>
#include "include_base_utils.h"
-#include "cryptonote_basic_impl.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
#include "tx_pool.h"
#include "blockchain.h"
#include "blockchain_db/blockchain_db.h"
-#include "cryptonote_format_utils.h"
-#include "cryptonote_boost_serialization.h"
+#include "cryptonote_basic/cryptonote_boost_serialization.h"
#include "cryptonote_config.h"
-#include "miner.h"
+#include "cryptonote_basic/miner.h"
#include "misc_language.h"
#include "profile_tools.h"
#include "file_io_utils.h"
@@ -49,8 +48,8 @@
#include "common/boost_serialization_helper.h"
#include "warnings.h"
#include "crypto/hash.h"
-#include "cryptonote_core/checkpoints.h"
-#include "cryptonote_core/cryptonote_core.h"
+#include "cryptonote_basic/checkpoints.h"
+#include "cryptonote_core.h"
#include "ringct/rctSigs.h"
#include "common/perf_timer.h"
#if defined(PER_BLOCK_CHECKPOINT)
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index cd452faf4..c806c3505 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -42,16 +42,16 @@
#include "syncobj.h"
#include "string_tools.h"
-#include "cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic.h"
#include "common/util.h"
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
#include "rpc/core_rpc_server_commands_defs.h"
-#include "difficulty.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
-#include "verification_context.h"
+#include "cryptonote_basic/difficulty.h"
+#include "cryptonote_tx_utils.h"
+#include "cryptonote_basic/verification_context.h"
#include "crypto/hash.h"
-#include "checkpoints.h"
-#include "hardfork.h"
+#include "cryptonote_basic/checkpoints.h"
+#include "cryptonote_basic/hardfork.h"
#include "blockchain_db/blockchain_db.h"
namespace cryptonote
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 900dc58ba..b940dba3c 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -38,11 +38,11 @@ using namespace epee;
#include "warnings.h"
#include "crypto/crypto.h"
#include "cryptonote_config.h"
-#include "cryptonote_format_utils.h"
+#include "cryptonote_tx_utils.h"
#include "misc_language.h"
#include <csignal>
#include <p2p/net_node.h>
-#include "cryptonote_core/checkpoints.h"
+#include "cryptonote_basic/checkpoints.h"
#include "ringct/rctTypes.h"
#include "blockchain_db/blockchain_db.h"
#include "blockchain_db/lmdb/db_lmdb.h"
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 1b9518c96..fe1d11916 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -41,9 +41,9 @@
#include "storages/portable_storage_template_helper.h"
#include "tx_pool.h"
#include "blockchain.h"
-#include "miner.h"
-#include "connection_context.h"
-#include "cryptonote_core/cryptonote_stat_info.h"
+#include "cryptonote_basic/miner.h"
+#include "cryptonote_basic/connection_context.h"
+#include "cryptonote_basic/cryptonote_stat_info.h"
#include "warnings.h"
#include "crypto/hash.h"
diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp
new file mode 100644
index 000000000..42e612e2f
--- /dev/null
+++ b/src/cryptonote_core/cryptonote_tx_utils.cpp
@@ -0,0 +1,493 @@
+// Copyright (c) 2014-2016, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#include "include_base_utils.h"
+using namespace epee;
+
+#include "cryptonote_tx_utils.h"
+#include "cryptonote_config.h"
+#include "cryptonote_basic/miner.h"
+#include "crypto/crypto.h"
+#include "crypto/hash.h"
+#include "ringct/rctSigs.h"
+
+namespace cryptonote
+{
+ //---------------------------------------------------------------
+ bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce, size_t max_outs, uint8_t hard_fork_version) {
+ tx.vin.clear();
+ tx.vout.clear();
+ tx.extra.clear();
+
+ keypair txkey = keypair::generate();
+ add_tx_pub_key_to_extra(tx, txkey.pub);
+ if(!extra_nonce.empty())
+ if(!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce))
+ return false;
+
+ txin_gen in;
+ in.height = height;
+
+ uint64_t block_reward;
+ if(!get_block_reward(median_size, current_block_size, already_generated_coins, block_reward, hard_fork_version))
+ {
+ LOG_PRINT_L0("Block is too big");
+ return false;
+ }
+
+#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
+ LOG_PRINT_L1("Creating block template: reward " << block_reward <<
+ ", fee " << fee);
+#endif
+ block_reward += fee;
+
+ // from hard fork 2, we cut out the low significant digits. This makes the tx smaller, and
+ // keeps the paid amount almost the same. The unpaid remainder gets pushed back to the
+ // emission schedule
+ // from hard fork 4, we use a single "dusty" output. This makes the tx even smaller,
+ // and avoids the quantization. These outputs will be added as rct outputs with identity
+ // masks, to they can be used as rct inputs.
+ if (hard_fork_version >= 2 && hard_fork_version < 4) {
+ block_reward = block_reward - block_reward % ::config::BASE_REWARD_CLAMP_THRESHOLD;
+ }
+
+ std::vector<uint64_t> out_amounts;
+ decompose_amount_into_digits(block_reward, hard_fork_version >= 2 ? 0 : ::config::DEFAULT_DUST_THRESHOLD,
+ [&out_amounts](uint64_t a_chunk) { out_amounts.push_back(a_chunk); },
+ [&out_amounts](uint64_t a_dust) { out_amounts.push_back(a_dust); });
+
+ CHECK_AND_ASSERT_MES(1 <= max_outs, false, "max_out must be non-zero");
+ if (height == 0 || hard_fork_version >= 4)
+ {
+ // the genesis block was not decomposed, for unknown reasons
+ while (max_outs < out_amounts.size())
+ {
+ //out_amounts[out_amounts.size() - 2] += out_amounts.back();
+ //out_amounts.resize(out_amounts.size() - 1);
+ out_amounts[1] += out_amounts[0];
+ for (size_t n = 1; n < out_amounts.size(); ++n)
+ out_amounts[n - 1] = out_amounts[n];
+ out_amounts.resize(out_amounts.size() - 1);
+ }
+ }
+ else
+ {
+ CHECK_AND_ASSERT_MES(max_outs >= out_amounts.size(), false, "max_out exceeded");
+ }
+
+ uint64_t summary_amounts = 0;
+ for (size_t no = 0; no < out_amounts.size(); no++)
+ {
+ crypto::key_derivation derivation = AUTO_VAL_INIT(derivation);;
+ crypto::public_key out_eph_public_key = AUTO_VAL_INIT(out_eph_public_key);
+ bool r = crypto::generate_key_derivation(miner_address.m_view_public_key, txkey.sec, derivation);
+ CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to generate_key_derivation(" << miner_address.m_view_public_key << ", " << txkey.sec << ")");
+
+ r = crypto::derive_public_key(derivation, no, miner_address.m_spend_public_key, out_eph_public_key);
+ CHECK_AND_ASSERT_MES(r, false, "while creating outs: failed to derive_public_key(" << derivation << ", " << no << ", "<< miner_address.m_spend_public_key << ")");
+
+ txout_to_key tk;
+ tk.key = out_eph_public_key;
+
+ tx_out out;
+ summary_amounts += out.amount = out_amounts[no];
+ out.target = tk;
+ tx.vout.push_back(out);
+ }
+
+ CHECK_AND_ASSERT_MES(summary_amounts == block_reward, false, "Failed to construct miner tx, summary_amounts = " << summary_amounts << " not equal block_reward = " << block_reward);
+
+ if (hard_fork_version >= 4)
+ tx.version = 2;
+ else
+ tx.version = 1;
+
+ //lock
+ tx.unlock_time = height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW;
+ tx.vin.push_back(in);
+ //LOG_PRINT("MINER_TX generated ok, block_reward=" << print_money(block_reward) << "(" << print_money(block_reward - fee) << "+" << print_money(fee)
+ // << "), current_block_size=" << current_block_size << ", already_generated_coins=" << already_generated_coins << ", tx_id=" << get_transaction_hash(tx), LOG_LEVEL_2);
+ return true;
+ }
+ //---------------------------------------------------------------
+ crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const account_keys &sender_keys)
+ {
+ if (destinations.empty())
+ return null_pkey;
+ for (size_t n = 1; n < destinations.size(); ++n)
+ {
+ if (!memcmp(&destinations[n].addr, &sender_keys.m_account_address, sizeof(destinations[0].addr)))
+ continue;
+ if (destinations[n].amount == 0)
+ continue;
+ if (memcmp(&destinations[n].addr, &destinations[0].addr, sizeof(destinations[0].addr)))
+ return null_pkey;
+ }
+ return destinations[0].addr.m_view_public_key;
+ }
+ //---------------------------------------------------------------
+ bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct)
+ {
+ std::vector<rct::key> amount_keys;
+ tx.set_null();
+ amount_keys.clear();
+
+ tx.version = rct ? 2 : 1;
+ tx.unlock_time = unlock_time;
+
+ tx.extra = extra;
+ keypair txkey = keypair::generate();
+ remove_field_from_tx_extra(tx.extra, typeid(tx_extra_pub_key));
+ add_tx_pub_key_to_extra(tx, txkey.pub);
+ tx_key = txkey.sec;
+
+ // if we have a stealth payment id, find it and encrypt it with the tx key now
+ std::vector<tx_extra_field> tx_extra_fields;
+ if (parse_tx_extra(tx.extra, tx_extra_fields))
+ {
+ tx_extra_nonce extra_nonce;
+ if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce))
+ {
+ crypto::hash8 payment_id = null_hash8;
+ if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id))
+ {
+ LOG_PRINT_L2("Encrypting payment id " << payment_id);
+ crypto::public_key view_key_pub = get_destination_view_key_pub(destinations, sender_account_keys);
+ if (view_key_pub == null_pkey)
+ {
+ LOG_ERROR("Destinations have to have exactly one output to support encrypted payment ids");
+ return false;
+ }
+
+ if (!encrypt_payment_id(payment_id, view_key_pub, txkey.sec))
+ {
+ LOG_ERROR("Failed to encrypt payment id");
+ return false;
+ }
+
+ std::string extra_nonce;
+ set_encrypted_payment_id_to_tx_extra_nonce(extra_nonce, payment_id);
+ remove_field_from_tx_extra(tx.extra, typeid(tx_extra_nonce));
+ if (!add_extra_nonce_to_tx_extra(tx.extra, extra_nonce))
+ {
+ LOG_ERROR("Failed to add encrypted payment id to tx extra");
+ return false;
+ }
+ LOG_PRINT_L1("Encrypted payment ID: " << payment_id);
+ }
+ }
+ }
+ else
+ {
+ LOG_ERROR("Failed to parse tx extra");
+ return false;
+ }
+
+ struct input_generation_context_data
+ {
+ keypair in_ephemeral;
+ };
+ std::vector<input_generation_context_data> in_contexts;
+
+ uint64_t summary_inputs_money = 0;
+ //fill inputs
+ int idx = -1;
+ for(const tx_source_entry& src_entr: sources)
+ {
+ ++idx;
+ if(src_entr.real_output >= src_entr.outputs.size())
+ {
+ LOG_ERROR("real_output index (" << src_entr.real_output << ")bigger than output_keys.size()=" << src_entr.outputs.size());
+ return false;
+ }
+ summary_inputs_money += src_entr.amount;
+
+ //key_derivation recv_derivation;
+ in_contexts.push_back(input_generation_context_data());
+ keypair& in_ephemeral = in_contexts.back().in_ephemeral;
+ crypto::key_image img;
+ if(!generate_key_image_helper(sender_account_keys, src_entr.real_out_tx_key, src_entr.real_output_in_tx_index, in_ephemeral, img))
+ return false;
+
+ //check that derivated key is equal with real output key
+ if( !(in_ephemeral.pub == src_entr.outputs[src_entr.real_output].second.dest) )
+ {
+ LOG_ERROR("derived public key mismatch with output public key at index " << idx << ", real out " << src_entr.real_output << "! "<< ENDL << "derived_key:"
+ << string_tools::pod_to_hex(in_ephemeral.pub) << ENDL << "real output_public_key:"
+ << string_tools::pod_to_hex(src_entr.outputs[src_entr.real_output].second) );
+ LOG_ERROR("amount " << src_entr.amount << ", rct " << src_entr.rct);
+ LOG_ERROR("tx pubkey " << src_entr.real_out_tx_key << ", real_output_in_tx_index " << src_entr.real_output_in_tx_index);
+ return false;
+ }
+
+ //put key image into tx input
+ txin_to_key input_to_key;
+ input_to_key.amount = src_entr.amount;
+ input_to_key.k_image = img;
+
+ //fill outputs array and use relative offsets
+ for(const tx_source_entry::output_entry& out_entry: src_entr.outputs)
+ input_to_key.key_offsets.push_back(out_entry.first);
+
+ input_to_key.key_offsets = absolute_output_offsets_to_relative(input_to_key.key_offsets);
+ tx.vin.push_back(input_to_key);
+ }
+
+ // "Shuffle" outs
+ std::vector<tx_destination_entry> shuffled_dsts(destinations);
+ std::sort(shuffled_dsts.begin(), shuffled_dsts.end(), [](const tx_destination_entry& de1, const tx_destination_entry& de2) { return de1.amount < de2.amount; } );
+
+ uint64_t summary_outs_money = 0;
+ //fill outputs
+ size_t output_index = 0;
+ for(const tx_destination_entry& dst_entr: shuffled_dsts)
+ {
+ CHECK_AND_ASSERT_MES(dst_entr.amount > 0 || tx.version > 1, false, "Destination with wrong amount: " << dst_entr.amount);
+ crypto::key_derivation derivation;
+ crypto::public_key out_eph_public_key;
+ bool r = crypto::generate_key_derivation(dst_entr.addr.m_view_public_key, txkey.sec, derivation);
+ CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to generate_key_derivation(" << dst_entr.addr.m_view_public_key << ", " << txkey.sec << ")");
+
+ if (tx.version > 1)
+ {
+ crypto::secret_key scalar1;
+ crypto::derivation_to_scalar(derivation, output_index, scalar1);
+ amount_keys.push_back(rct::sk2rct(scalar1));
+ }
+ r = crypto::derive_public_key(derivation, output_index, dst_entr.addr.m_spend_public_key, out_eph_public_key);
+ CHECK_AND_ASSERT_MES(r, false, "at creation outs: failed to derive_public_key(" << derivation << ", " << output_index << ", "<< dst_entr.addr.m_spend_public_key << ")");
+
+ tx_out out;
+ out.amount = dst_entr.amount;
+ txout_to_key tk;
+ tk.key = out_eph_public_key;
+ out.target = tk;
+ tx.vout.push_back(out);
+ output_index++;
+ summary_outs_money += dst_entr.amount;
+ }
+
+ //check money
+ if(summary_outs_money > summary_inputs_money )
+ {
+ LOG_ERROR("Transaction inputs money ("<< summary_inputs_money << ") less than outputs money (" << summary_outs_money << ")");
+ return false;
+ }
+
+ // check for watch only wallet
+ bool zero_secret_key = true;
+ for (size_t i = 0; i < sizeof(sender_account_keys.m_spend_secret_key); ++i)
+ zero_secret_key &= (sender_account_keys.m_spend_secret_key.data[i] == 0);
+ if (zero_secret_key)
+ {
+ MDEBUG("Null secret key, skipping signatures");
+ }
+
+ if (tx.version == 1)
+ {
+ //generate ring signatures
+ crypto::hash tx_prefix_hash;
+ get_transaction_prefix_hash(tx, tx_prefix_hash);
+
+ std::stringstream ss_ring_s;
+ size_t i = 0;
+ for(const tx_source_entry& src_entr: sources)
+ {
+ ss_ring_s << "pub_keys:" << ENDL;
+ std::vector<const crypto::public_key*> keys_ptrs;
+ std::vector<crypto::public_key> keys(src_entr.outputs.size());
+ size_t ii = 0;
+ for(const tx_source_entry::output_entry& o: src_entr.outputs)
+ {
+ keys[ii] = rct2pk(o.second.dest);
+ keys_ptrs.push_back(&keys[ii]);
+ ss_ring_s << o.second.dest << ENDL;
+ ++ii;
+ }
+
+ tx.signatures.push_back(std::vector<crypto::signature>());
+ std::vector<crypto::signature>& sigs = tx.signatures.back();
+ sigs.resize(src_entr.outputs.size());
+ if (!zero_secret_key)
+ crypto::generate_ring_signature(tx_prefix_hash, boost::get<txin_to_key>(tx.vin[i]).k_image, keys_ptrs, in_contexts[i].in_ephemeral.sec, src_entr.real_output, sigs.data());
+ ss_ring_s << "signatures:" << ENDL;
+ std::for_each(sigs.begin(), sigs.end(), [&](const crypto::signature& s){ss_ring_s << s << ENDL;});
+ ss_ring_s << "prefix_hash:" << tx_prefix_hash << ENDL << "in_ephemeral_key: " << in_contexts[i].in_ephemeral.sec << ENDL << "real_output: " << src_entr.real_output;
+ i++;
+ }
+
+ MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL << ss_ring_s.str());
+ }
+ else
+ {
+ size_t n_total_outs = sources[0].outputs.size(); // only for non-simple rct
+
+ // the non-simple version is slightly smaller, but assumes all real inputs
+ // are on the same index, so can only be used if there just one ring.
+ bool use_simple_rct = sources.size() > 1;
+
+ if (!use_simple_rct)
+ {
+ // non simple ringct requires all real inputs to be at the same index for all inputs
+ for(const tx_source_entry& src_entr: sources)
+ {
+ if(src_entr.real_output != sources.begin()->real_output)
+ {
+ LOG_ERROR("All inputs must have the same index for non-simple ringct");
+ return false;
+ }
+ }
+
+ // enforce same mixin for all outputs
+ for (size_t i = 1; i < sources.size(); ++i) {
+ if (n_total_outs != sources[i].outputs.size()) {
+ LOG_ERROR("Non-simple ringct transaction has varying mixin");
+ return false;
+ }
+ }
+ }
+
+ uint64_t amount_in = 0, amount_out = 0;
+ rct::ctkeyV inSk;
+ // mixRing indexing is done the other way round for simple
+ rct::ctkeyM mixRing(use_simple_rct ? sources.size() : n_total_outs);
+ rct::keyV destinations;
+ std::vector<uint64_t> inamounts, outamounts;
+ std::vector<unsigned int> index;
+ for (size_t i = 0; i < sources.size(); ++i)
+ {
+ rct::ctkey ctkey;
+ amount_in += sources[i].amount;
+ inamounts.push_back(sources[i].amount);
+ index.push_back(sources[i].real_output);
+ // inSk: (secret key, mask)
+ ctkey.dest = rct::sk2rct(in_contexts[i].in_ephemeral.sec);
+ ctkey.mask = sources[i].mask;
+ inSk.push_back(ctkey);
+ // inPk: (public key, commitment)
+ // will be done when filling in mixRing
+ }
+ for (size_t i = 0; i < tx.vout.size(); ++i)
+ {
+ destinations.push_back(rct::pk2rct(boost::get<txout_to_key>(tx.vout[i].target).key));
+ outamounts.push_back(tx.vout[i].amount);
+ amount_out += tx.vout[i].amount;
+ }
+
+ if (use_simple_rct)
+ {
+ // mixRing indexing is done the other way round for simple
+ for (size_t i = 0; i < sources.size(); ++i)
+ {
+ mixRing[i].resize(sources[i].outputs.size());
+ for (size_t n = 0; n < sources[i].outputs.size(); ++n)
+ {
+ mixRing[i][n] = sources[i].outputs[n].second;
+ }
+ }
+ }
+ else
+ {
+ for (size_t i = 0; i < n_total_outs; ++i) // same index assumption
+ {
+ mixRing[i].resize(sources.size());
+ for (size_t n = 0; n < sources.size(); ++n)
+ {
+ mixRing[i][n] = sources[n].outputs[i].second;
+ }
+ }
+ }
+
+ // fee
+ if (!use_simple_rct && amount_in > amount_out)
+ outamounts.push_back(amount_in - amount_out);
+
+ // zero out all amounts to mask rct outputs, real amounts are now encrypted
+ for (size_t i = 0; i < tx.vin.size(); ++i)
+ {
+ if (sources[i].rct)
+ boost::get<txin_to_key>(tx.vin[i]).amount = 0;
+ }
+ for (size_t i = 0; i < tx.vout.size(); ++i)
+ tx.vout[i].amount = 0;
+
+ crypto::hash tx_prefix_hash;
+ get_transaction_prefix_hash(tx, tx_prefix_hash);
+ rct::ctkeyV outSk;
+ if (use_simple_rct)
+ tx.rct_signatures = rct::genRctSimple(rct::hash2rct(tx_prefix_hash), inSk, destinations, inamounts, outamounts, amount_in - amount_out, mixRing, amount_keys, index, outSk);
+ else
+ tx.rct_signatures = rct::genRct(rct::hash2rct(tx_prefix_hash), inSk, destinations, outamounts, mixRing, amount_keys, sources[0].real_output, outSk); // same index assumption
+
+ CHECK_AND_ASSERT_MES(tx.vout.size() == outSk.size(), false, "outSk size does not match vout");
+
+ MCINFO("construct_tx", "transaction_created: " << get_transaction_hash(tx) << ENDL << obj_to_json_str(tx) << ENDL);
+ }
+
+ return true;
+ }
+ //---------------------------------------------------------------
+ bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time)
+ {
+ crypto::secret_key tx_key;
+ return construct_tx_and_get_tx_key(sender_account_keys, sources, destinations, extra, tx, unlock_time, tx_key);
+ }
+ //---------------------------------------------------------------
+ bool generate_genesis_block(
+ block& bl
+ , std::string const & genesis_tx
+ , uint32_t nonce
+ )
+ {
+ //genesis block
+ bl = boost::value_initialized<block>();
+
+
+ account_public_address ac = boost::value_initialized<account_public_address>();
+ std::vector<size_t> sz;
+ construct_miner_tx(0, 0, 0, 0, 0, ac, bl.miner_tx); // zero fee in genesis
+ blobdata txb = tx_to_blob(bl.miner_tx);
+ std::string hex_tx_represent = string_tools::buff_to_hex_nodelimer(txb);
+
+ std::string genesis_coinbase_tx_hex = config::GENESIS_TX;
+
+ blobdata tx_bl;
+ string_tools::parse_hexstr_to_binbuff(genesis_coinbase_tx_hex, tx_bl);
+ bool r = parse_and_validate_tx_from_blob(tx_bl, bl.miner_tx);
+ CHECK_AND_ASSERT_MES(r, false, "failed to parse coinbase tx from hard coded blob");
+ bl.major_version = CURRENT_BLOCK_MAJOR_VERSION;
+ bl.minor_version = CURRENT_BLOCK_MINOR_VERSION;
+ bl.timestamp = 0;
+ bl.nonce = nonce;
+ miner::find_nonce_for_given_block(bl, 1, 0);
+ return true;
+ }
+ //---------------------------------------------------------------
+}
diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h
new file mode 100644
index 000000000..859318fe5
--- /dev/null
+++ b/src/cryptonote_core/cryptonote_tx_utils.h
@@ -0,0 +1,101 @@
+// Copyright (c) 2014-2016, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
+
+#pragma once
+#include "cryptonote_basic/cryptonote_format_utils.h"
+#include <boost/serialization/vector.hpp>
+#include <boost/serialization/utility.hpp>
+
+namespace cryptonote
+{
+ //---------------------------------------------------------------
+ bool construct_miner_tx(size_t height, size_t median_size, uint64_t already_generated_coins, size_t current_block_size, uint64_t fee, const account_public_address &miner_address, transaction& tx, const blobdata& extra_nonce = blobdata(), size_t max_outs = 999, uint8_t hard_fork_version = 1);
+
+ struct tx_source_entry
+ {
+ typedef std::pair<uint64_t, rct::ctkey> output_entry;
+
+ std::vector<output_entry> outputs; //index + key + optional ringct commitment
+ size_t real_output; //index in outputs vector of real output_entry
+ crypto::public_key real_out_tx_key; //incoming real tx public key
+ size_t real_output_in_tx_index; //index in transaction outputs vector
+ uint64_t amount; //money
+ bool rct; //true if the output is rct
+ rct::key mask; //ringct amount mask
+
+ void push_output(uint64_t idx, const crypto::public_key &k, uint64_t amount) { outputs.push_back(std::make_pair(idx, rct::ctkey({rct::pk2rct(k), rct::zeroCommit(amount)}))); }
+ };
+
+ struct tx_destination_entry
+ {
+ uint64_t amount; //money
+ account_public_address addr; //destination address
+
+ tx_destination_entry() : amount(0), addr(AUTO_VAL_INIT(addr)) { }
+ tx_destination_entry(uint64_t a, const account_public_address &ad) : amount(a), addr(ad) { }
+
+ BEGIN_SERIALIZE_OBJECT()
+ VARINT_FIELD(amount)
+ FIELD(addr)
+ END_SERIALIZE()
+ };
+
+ //---------------------------------------------------------------
+ crypto::public_key get_destination_view_key_pub(const std::vector<tx_destination_entry> &destinations, const account_keys &sender_keys);
+ bool construct_tx(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time);
+ bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, bool rct = false);
+
+ bool generate_genesis_block(
+ block& bl
+ , std::string const & genesis_tx
+ , uint32_t nonce
+ );
+
+}
+
+BOOST_CLASS_VERSION(cryptonote::tx_source_entry, 0)
+
+namespace boost
+{
+ namespace serialization
+ {
+ template <class Archive>
+ inline void serialize(Archive &a, cryptonote::tx_source_entry &x, const boost::serialization::version_type ver)
+ {
+ a & x.outputs;
+ a & x.real_output;
+ a & x.real_out_tx_key;
+ a & x.real_output_in_tx_index;
+ a & x.amount;
+ a & x.rct;
+ a & x.mask;
+ }
+ }
+}
diff --git a/src/cryptonote_core/miner.cpp b/src/cryptonote_core/miner.cpp
deleted file mode 100644
index 88c631f80..000000000
--- a/src/cryptonote_core/miner.cpp
+++ /dev/null
@@ -1,414 +0,0 @@
-// Copyright (c) 2014-2016, The Monero Project
-//
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without modification, are
-// permitted provided that the following conditions are met:
-//
-// 1. Redistributions of source code must retain the above copyright notice, this list of
-// conditions and the following disclaimer.
-//
-// 2. Redistributions in binary form must reproduce the above copyright notice, this list
-// of conditions and the following disclaimer in the documentation and/or other
-// materials provided with the distribution.
-//
-// 3. Neither the name of the copyright holder nor the names of its contributors may be
-// used to endorse or promote products derived from this software without specific
-// prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
-// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
-// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
-// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
-// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-//
-// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
-
-#include <sstream>
-#include <numeric>
-#include <boost/utility/value_init.hpp>
-#include <boost/interprocess/detail/atomic.hpp>
-#include <boost/limits.hpp>
-#include "misc_language.h"
-#include "include_base_utils.h"
-#include "cryptonote_basic_impl.h"
-#include "cryptonote_format_utils.h"
-#include "file_io_utils.h"
-#include "common/command_line.h"
-#include "string_coding.h"
-#include "storages/portable_storage_template_helper.h"
-
-#undef MONERO_DEFAULT_LOG_CATEGORY
-#define MONERO_DEFAULT_LOG_CATEGORY "miner"
-
-using namespace epee;
-
-#include "miner.h"
-
-
-extern "C" void slow_hash_allocate_state();
-extern "C" void slow_hash_free_state();
-namespace cryptonote
-{
-
- namespace
- {
- const command_line::arg_descriptor<std::string> arg_extra_messages = {"extra-messages-file", "Specify file for extra messages to include into coinbase transactions", "", true};
- const command_line::arg_descriptor<std::string> arg_start_mining = {"start-mining", "Specify wallet address to mining for", "", true};
- const command_line::arg_descriptor<uint32_t> arg_mining_threads = {"mining-threads", "Specify mining threads count", 0, true};
- }
-
-
- miner::miner(i_miner_handler* phandler):m_stop(1),
- m_template(boost::value_initialized<block>()),
- m_template_no(0),
- m_diffic(0),
- m_thread_index(0),
- m_phandler(phandler),
- m_height(0),
- m_pausers_count(0),
- m_threads_total(0),
- m_starter_nonce(0),
- m_last_hr_merge_time(0),
- m_hashes(0),
- m_do_print_hashrate(false),
- m_do_mining(false),
- m_current_hash_rate(0)
- {
-
- }
- //-----------------------------------------------------------------------------------------------------
- miner::~miner()
- {
- stop();
- }
- //-----------------------------------------------------------------------------------------------------
- bool miner::set_block_template(const block& bl, const difficulty_type& di, uint64_t height)
- {
- CRITICAL_REGION_LOCAL(m_template_lock);
- m_template = bl;
- m_diffic = di;
- m_height = height;
- ++m_template_no;
- m_starter_nonce = crypto::rand<uint32_t>();
- return true;
- }
- //-----------------------------------------------------------------------------------------------------
- bool miner::on_block_chain_update()
- {
- if(!is_mining())
- return true;
-
- return request_block_template();
- }
- //-----------------------------------------------------------------------------------------------------
- bool miner::request_block_template()
- {
- block bl = AUTO_VAL_INIT(bl);
- difficulty_type di = AUTO_VAL_INIT(di);
- uint64_t height = AUTO_VAL_INIT(height);
- cryptonote::blobdata extra_nonce;
- if(m_extra_messages.size() && m_config.current_extra_message_index < m_extra_messages.size())
- {
- extra_nonce = m_extra_messages[m_config.current_extra_message_index];
- }
-
- if(!m_phandler->get_block_template(bl, m_mine_address, di, height, extra_nonce))
- {
- LOG_ERROR("Failed to get_block_template(), stopping mining");
- return false;
- }
- set_block_template(bl, di, height);
- return true;
- }
- //-----------------------------------------------------------------------------------------------------
- bool miner::on_idle()
- {
- m_update_block_template_interval.do_call([&](){
- if(is_mining())request_block_template();
- return true;
- });
-
- m_update_merge_hr_interval.do_call([&](){
- merge_hr();
- return true;
- });
-
- return true;
- }
- //-----------------------------------------------------------------------------------------------------
- void miner::do_print_hashrate(bool do_hr)
- {
- m_do_print_hashrate = do_hr;
- }
- //-----------------------------------------------------------------------------------------------------
- void miner::merge_hr()
- {
- if(m_last_hr_merge_time && is_mining())
- {
- m_current_hash_rate = m_hashes * 1000 / ((misc_utils::get_tick_count() - m_last_hr_merge_time + 1));
- CRITICAL_REGION_LOCAL(m_last_hash_rates_lock);
- m_last_hash_rates.push_back(m_current_hash_rate);
- if(m_last_hash_rates.size() > 19)
- m_last_hash_rates.pop_front();
- if(m_do_print_hashrate)
- {
- uint64_t total_hr = std::accumulate(m_last_hash_rates.begin(), m_last_hash_rates.end(), 0);
- float hr = static_cast<float>(total_hr)/static_cast<float>(m_last_hash_rates.size());
- std::cout << "hashrate: " << std::setprecision(4) << std::fixed << hr << ENDL;
- }
- }
- m_last_hr_merge_time = misc_utils::get_tick_count();
- m_hashes = 0;
- }
- //-----------------------------------------------------------------------------------------------------
- void miner::init_options(boost::program_options::options_description& desc)
- {
- command_line::add_arg(desc, arg_extra_messages);
- command_line::add_arg(desc, arg_start_mining);
- command_line::add_arg(desc, arg_mining_threads);
- }
- //-----------------------------------------------------------------------------------------------------
- bool miner::init(const boost::program_options::variables_map& vm, bool testnet)
- {
- if(command_line::has_arg(vm, arg_extra_messages))
- {
- std::string buff;
- bool r = file_io_utils::load_file_to_string(command_line::get_arg(vm, arg_extra_messages), buff);
- CHECK_AND_ASSERT_MES(r, false, "Failed to load file with extra messages: " << command_line::get_arg(vm, arg_extra_messages));
- std::vector<std::string> extra_vec;
- boost::split(extra_vec, buff, boost::is_any_of("\n"), boost::token_compress_on );
- m_extra_messages.resize(extra_vec.size());
- for(size_t i = 0; i != extra_vec.size(); i++)
- {
- string_tools::trim(extra_vec[i]);
- if(!extra_vec[i].size())
- continue;
- std::string buff = string_encoding::base64_decode(extra_vec[i]);
- if(buff != "0")
- m_extra_messages[i] = buff;
- }
- m_config_folder_path = boost::filesystem::path(command_line::get_arg(vm, arg_extra_messages)).parent_path().string();
- m_config = AUTO_VAL_INIT(m_config);
- epee::serialization::load_t_from_json_file(m_config, m_config_folder_path + "/" + MINER_CONFIG_FILE_NAME);
- MINFO("Loaded " << m_extra_messages.size() << " extra messages, current index " << m_config.current_extra_message_index);
- }
-
- if(command_line::has_arg(vm, arg_start_mining))
- {
- if(!cryptonote::get_account_address_from_str(m_mine_address, testnet, command_line::get_arg(vm, arg_start_mining)))
- {
- LOG_ERROR("Target account address " << command_line::get_arg(vm, arg_start_mining) << " has wrong format, starting daemon canceled");
- return false;
- }
- m_threads_total = 1;
- m_do_mining = true;
- if(command_line::has_arg(vm, arg_mining_threads))
- {
- m_threads_total = command_line::get_arg(vm, arg_mining_threads);
- }
- }
-
- return true;
- }
- //-----------------------------------------------------------------------------------------------------
- bool miner::is_mining() const
- {
- 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)
- {
- m_mine_address = adr;
- m_threads_total = static_cast<uint32_t>(threads_count);
- m_starter_nonce = crypto::rand<uint32_t>();
- CRITICAL_REGION_LOCAL(m_threads_lock);
- if(is_mining())
- {
- LOG_ERROR("Starting miner but it's already started");
- return false;
- }
-
- if(!m_threads.empty())
- {
- LOG_ERROR("Unable to start miner because there are active mining threads");
- return false;
- }
-
- if(!m_template_no)
- request_block_template();//lets update block template
-
- boost::interprocess::ipcdetail::atomic_write32(&m_stop, 0);
- boost::interprocess::ipcdetail::atomic_write32(&m_thread_index, 0);
-
- for(size_t i = 0; i != threads_count; i++)
- {
- m_threads.push_back(boost::thread(attrs, boost::bind(&miner::worker_thread, this)));
- }
-
- LOG_PRINT_L0("Mining has started with " << threads_count << " threads, good luck!" );
- return true;
- }
- //-----------------------------------------------------------------------------------------------------
- uint64_t miner::get_speed() const
- {
- if(is_mining()) {
- return m_current_hash_rate;
- }
- else {
- return 0;
- }
- }
- //-----------------------------------------------------------------------------------------------------
- void miner::send_stop_signal()
- {
- boost::interprocess::ipcdetail::atomic_write32(&m_stop, 1);
- }
- //-----------------------------------------------------------------------------------------------------
- bool miner::stop()
- {
- MTRACE("Miner has received stop signal");
-
- if (!is_mining())
- {
- MDEBUG("Not mining - nothing to stop" );
- return true;
- }
-
- send_stop_signal();
- CRITICAL_REGION_LOCAL(m_threads_lock);
-
- for(boost::thread& th: m_threads)
- th.join();
-
- MINFO("Mining has been stopped, " << m_threads.size() << " finished" );
- m_threads.clear();
- return true;
- }
- //-----------------------------------------------------------------------------------------------------
- bool miner::find_nonce_for_given_block(block& bl, const difficulty_type& diffic, uint64_t height)
- {
- for(; bl.nonce != std::numeric_limits<uint32_t>::max(); bl.nonce++)
- {
- crypto::hash h;
- get_block_longhash(bl, h, height);
-
- if(check_hash(h, diffic))
- {
- return true;
- }
- }
- return false;
- }
- //-----------------------------------------------------------------------------------------------------
- void miner::on_synchronized()
- {
- if(m_do_mining)
- {
- boost::thread::attributes attrs;
- attrs.set_stack_size(THREAD_STACK_SIZE);
-
- start(m_mine_address, m_threads_total, attrs);
- }
- }
- //-----------------------------------------------------------------------------------------------------
- void miner::pause()
- {
- CRITICAL_REGION_LOCAL(m_miners_count_lock);
- ++m_pausers_count;
- if(m_pausers_count == 1 && is_mining())
- MDEBUG("MINING PAUSED");
- }
- //-----------------------------------------------------------------------------------------------------
- void miner::resume()
- {
- CRITICAL_REGION_LOCAL(m_miners_count_lock);
- --m_pausers_count;
- if(m_pausers_count < 0)
- {
- m_pausers_count = 0;
- MERROR("Unexpected miner::resume() called");
- }
- if(!m_pausers_count && is_mining())
- MDEBUG("MINING RESUMED");
- }
- //-----------------------------------------------------------------------------------------------------
- bool miner::worker_thread()
- {
- uint32_t th_local_index = boost::interprocess::ipcdetail::atomic_inc32(&m_thread_index);
- MGINFO("Miner thread was started ["<< th_local_index << "]");
- MLOG_SET_THREAD_NAME(std::string("[miner ") + std::to_string(th_local_index) + "]");
- uint32_t nonce = m_starter_nonce + th_local_index;
- uint64_t height = 0;
- difficulty_type local_diff = 0;
- uint32_t local_template_ver = 0;
- block b;
- slow_hash_allocate_state();
- while(!m_stop)
- {
- if(m_pausers_count)//anti split workaround
- {
- misc_utils::sleep_no_w(100);
- continue;
- }
-
- if(local_template_ver != m_template_no)
- {
- CRITICAL_REGION_BEGIN(m_template_lock);
- b = m_template;
- local_diff = m_diffic;
- height = m_height;
- CRITICAL_REGION_END();
- local_template_ver = m_template_no;
- nonce = m_starter_nonce + th_local_index;
- }
-
- if(!local_template_ver)//no any set_block_template call
- {
- LOG_PRINT_L2("Block template not set yet");
- epee::misc_utils::sleep_no_w(1000);
- continue;
- }
-
- b.nonce = nonce;
- crypto::hash h;
- get_block_longhash(b, h, height);
-
- if(check_hash(h, local_diff))
- {
- //we lucky!
- ++m_config.current_extra_message_index;
- MGINFO_GREEN("Found block for difficulty: " << local_diff);
- if(!m_phandler->handle_block_found(b))
- {
- --m_config.current_extra_message_index;
- }else
- {
- //success update, lets update config
- if (!m_config_folder_path.empty())
- epee::serialization::store_t_to_json_file(m_config, m_config_folder_path + "/" + MINER_CONFIG_FILE_NAME);
- }
- }
- nonce+=m_threads_total;
- ++m_hashes;
- }
- slow_hash_free_state();
- MGINFO("Miner thread stopped ["<< th_local_index << "]");
- return true;
- }
- //-----------------------------------------------------------------------------------------------------
-}
-
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index e37ddec0d..9188f8329 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -34,8 +34,8 @@
#include <vector>
#include "tx_pool.h"
-#include "cryptonote_format_utils.h"
-#include "cryptonote_boost_serialization.h"
+#include "cryptonote_tx_utils.h"
+#include "cryptonote_basic/cryptonote_boost_serialization.h"
#include "cryptonote_config.h"
#include "blockchain.h"
#include "common/boost_serialization_helper.h"
diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h
index 2712f75bb..e9c9e3f36 100644
--- a/src/cryptonote_core/tx_pool.h
+++ b/src/cryptonote_core/tx_pool.h
@@ -41,8 +41,8 @@
#include "string_tools.h"
#include "syncobj.h"
#include "math_helper.h"
-#include "cryptonote_basic_impl.h"
-#include "verification_context.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
+#include "cryptonote_basic/verification_context.h"
#include "crypto/hash.h"
#include "rpc/core_rpc_server_commands_defs.h"
diff --git a/src/cryptonote_protocol/CMakeLists.txt b/src/cryptonote_protocol/CMakeLists.txt
index 65473b117..847090c32 100644
--- a/src/cryptonote_protocol/CMakeLists.txt
+++ b/src/cryptonote_protocol/CMakeLists.txt
@@ -35,6 +35,8 @@ source_group(cryptonote_protocol FILES ${CRYPTONOTE_PROTOCOL})
#monero_private_headers(cryptonote_protocol ${CRYPTONOTE_PROTOCOL})
monero_add_library(cryptonote_protocol ${CRYPTONOTE_PROTOCOL})
target_link_libraries(cryptonote_protocol
+ PUBLIC
+ p2p
PRIVATE
${EXTRA_LIBRARIES})
add_dependencies(cryptonote_protocol
diff --git a/src/cryptonote_protocol/cryptonote_protocol_defs.h b/src/cryptonote_protocol/cryptonote_protocol_defs.h
index 7adc69080..843504621 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_defs.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_defs.h
@@ -32,7 +32,7 @@
#include <list>
#include "serialization/keyvalue_serialization.h"
-#include "cryptonote_core/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic.h"
#include "cryptonote_protocol/blobdatatype.h"
namespace cryptonote
{
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h
index 4b2de39b9..7a3a2d325 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h
@@ -42,9 +42,9 @@
#include "warnings.h"
#include "cryptonote_protocol_defs.h"
#include "cryptonote_protocol_handler_common.h"
-#include "cryptonote_core/connection_context.h"
-#include "cryptonote_core/cryptonote_stat_info.h"
-#include "cryptonote_core/verification_context.h"
+#include "cryptonote_basic/connection_context.h"
+#include "cryptonote_basic/cryptonote_stat_info.h"
+#include "cryptonote_basic/verification_context.h"
// #include <netinet/in.h>
#include <boost/circular_buffer.hpp>
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index 1309ff742..151a661d9 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -39,7 +39,7 @@
#include <list>
#include <unordered_map>
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
#include "profile_tools.h"
#include "../../src/p2p/network_throttle-detail.hpp"
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler_common.h b/src/cryptonote_protocol/cryptonote_protocol_handler_common.h
index 06061f5d0..e3c67fdb2 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler_common.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler_common.h
@@ -32,7 +32,7 @@
#include "p2p/net_node_common.h"
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
-#include "cryptonote_core/connection_context.h"
+#include "cryptonote_basic/connection_context.h"
namespace cryptonote
{
/************************************************************************/
diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp
index 27f9d0fd7..8ed529737 100644
--- a/src/daemon/command_parser_executor.cpp
+++ b/src/daemon/command_parser_executor.cpp
@@ -37,11 +37,11 @@ namespace daemonize {
t_command_parser_executor::t_command_parser_executor(
uint32_t ip
, uint16_t port
- , const std::string &user_agent
+ , const boost::optional<tools::login>& login
, bool is_rpc
, cryptonote::core_rpc_server* rpc_server
)
- : m_executor(ip, port, user_agent, is_rpc, rpc_server)
+ : m_executor(ip, port, login, is_rpc, rpc_server)
{}
bool t_command_parser_executor::print_peer_list(const std::vector<std::string>& args)
@@ -271,17 +271,24 @@ bool t_command_parser_executor::start_mining(const std::vector<std::string>& arg
if(testnet)
std::cout << "Mining to a testnet address, make sure this is intentional!" << std::endl;
uint64_t threads_count = 1;
- if(args.size() > 2)
+ bool do_background_mining = false;
+ if(args.size() > 3)
{
return false;
}
- else if(args.size() == 2)
+
+ if(args.size() == 3)
+ {
+ do_background_mining = args[2] == "true";
+ }
+
+ if(args.size() >= 2)
{
bool ok = epee::string_tools::get_xtype_from_string(threads_count, args[1]);
threads_count = (ok && 0 < threads_count) ? threads_count : 1;
}
- m_executor.start_mining(adr, threads_count, testnet);
+ m_executor.start_mining(adr, threads_count, testnet, do_background_mining);
return true;
}
diff --git a/src/daemon/command_parser_executor.h b/src/daemon/command_parser_executor.h
index 15293ade9..1fe3e0f98 100644
--- a/src/daemon/command_parser_executor.h
+++ b/src/daemon/command_parser_executor.h
@@ -36,7 +36,10 @@
#pragma once
+#include <boost/optional/optional_fwd.hpp>
+
#include "daemon/rpc_command_executor.h"
+#include "common/common_fwd.h"
#include "rpc/core_rpc_server.h"
namespace daemonize {
@@ -49,7 +52,7 @@ public:
t_command_parser_executor(
uint32_t ip
, uint16_t port
- , const std::string &user_agent
+ , const boost::optional<tools::login>& login
, bool is_rpc
, cryptonote::core_rpc_server* rpc_server = NULL
);
diff --git a/src/daemon/command_server.cpp b/src/daemon/command_server.cpp
index 95fd3178c..4133b90d9 100644
--- a/src/daemon/command_server.cpp
+++ b/src/daemon/command_server.cpp
@@ -40,11 +40,11 @@ namespace p = std::placeholders;
t_command_server::t_command_server(
uint32_t ip
, uint16_t port
- , const std::string &user_agent
+ , const boost::optional<tools::login>& login
, bool is_rpc
, cryptonote::core_rpc_server* rpc_server
)
- : m_parser(ip, port, user_agent, is_rpc, rpc_server)
+ : m_parser(ip, port, login, is_rpc, rpc_server)
, m_command_lookup()
, m_is_rpc(is_rpc)
{
@@ -96,7 +96,7 @@ t_command_server::t_command_server(
m_command_lookup.set_handler(
"start_mining"
, std::bind(&t_command_parser_executor::start_mining, &m_parser, p::_1)
- , "Start mining for specified address, start_mining <addr> [<threads>], default 1 thread"
+ , "Start mining for specified address, start_mining <addr> [<threads>] [do_background_mining], default 1 thread, no background mining"
);
m_command_lookup.set_handler(
"stop_mining"
diff --git a/src/daemon/command_server.h b/src/daemon/command_server.h
index fb1702aae..9ecf06b9d 100644
--- a/src/daemon/command_server.h
+++ b/src/daemon/command_server.h
@@ -39,6 +39,8 @@ Passing RPC commands:
#pragma once
+#include <boost/optional/optional_fwd.hpp>
+#include "common/common_fwd.h"
#include "console_handler.h"
#include "daemon/command_parser_executor.h"
@@ -54,7 +56,7 @@ public:
t_command_server(
uint32_t ip
, uint16_t port
- , const std::string &user_agent
+ , const boost::optional<tools::login>& login
, bool is_rpc = true
, cryptonote::core_rpc_server* rpc_server = NULL
);
diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp
index 287c30cb4..e40136a71 100644
--- a/src/daemon/daemon.cpp
+++ b/src/daemon/daemon.cpp
@@ -33,6 +33,7 @@
#include "misc_log_ex.h"
#include "daemon/daemon.h"
+#include "common/password.h"
#include "common/util.h"
#include "daemon/core.h"
#include "daemon/p2p.h"
@@ -127,7 +128,8 @@ bool t_daemon::run(bool interactive)
if (interactive)
{
- rpc_commands = new daemonize::t_command_server(0, 0, "", false, mp_internals->rpc.get_server());
+ // The first three variables are not used when the fourth is false
+ rpc_commands = new daemonize::t_command_server(0, 0, boost::none, false, mp_internals->rpc.get_server());
rpc_commands->start_handling(std::bind(&daemonize::t_daemon::stop_p2p, this));
}
diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp
index e08065ccd..4822d8d8a 100644
--- a/src/daemon/main.cpp
+++ b/src/daemon/main.cpp
@@ -30,9 +30,10 @@
#include "common/command_line.h"
#include "common/scoped_message_writer.h"
+#include "common/password.h"
#include "common/util.h"
#include "cryptonote_core/cryptonote_core.h"
-#include "cryptonote_core/miner.h"
+#include "cryptonote_basic/miner.h"
#include "daemon/command_server.h"
#include "daemon/daemon.h"
#include "daemon/executor.h"
@@ -40,6 +41,7 @@
#include "misc_log_ex.h"
#include "p2p/net_node.h"
#include "rpc/core_rpc_server.h"
+#include "rpc/rpc_args.h"
#include "daemon/command_line_args.h"
#include "blockchain_db/db_types.h"
@@ -220,13 +222,13 @@ int main(int argc, char const * argv[])
if (command.size())
{
- auto rpc_ip_str = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_rpc_bind_ip);
+ const cryptonote::rpc_args::descriptors arg{};
+ auto rpc_ip_str = command_line::get_arg(vm, arg.rpc_bind_ip);
auto rpc_port_str = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_rpc_bind_port);
if (testnet_mode)
{
rpc_port_str = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_testnet_rpc_bind_port);
}
- auto user_agent = command_line::get_arg(vm, cryptonote::core_rpc_server::arg_user_agent);
uint32_t rpc_ip;
uint16_t rpc_port;
@@ -241,7 +243,20 @@ int main(int argc, char const * argv[])
return 1;
}
- daemonize::t_command_server rpc_commands{rpc_ip, rpc_port, user_agent};
+ boost::optional<tools::login> login{};
+ if (command_line::has_arg(vm, arg.rpc_login))
+ {
+ login = tools::login::parse(
+ command_line::get_arg(vm, arg.rpc_login), false, "Daemon client password"
+ );
+ if (!login)
+ {
+ std::cerr << "Failed to obtain password" << std::endl;
+ return 1;
+ }
+ }
+
+ daemonize::t_command_server rpc_commands{rpc_ip, rpc_port, std::move(login)};
if (rpc_commands.process_command_vec(command))
{
return 0;
diff --git a/src/daemon/rpc_command_executor.cpp b/src/daemon/rpc_command_executor.cpp
index f7d85b5ef..00b349b15 100644
--- a/src/daemon/rpc_command_executor.cpp
+++ b/src/daemon/rpc_command_executor.cpp
@@ -29,11 +29,12 @@
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "string_tools.h"
+#include "common/password.h"
#include "common/scoped_message_writer.h"
#include "daemon/rpc_command_executor.h"
#include "rpc/core_rpc_server_commands_defs.h"
#include "cryptonote_core/cryptonote_core.h"
-#include "cryptonote_core/hardfork.h"
+#include "cryptonote_basic/hardfork.h"
#include <boost/format.hpp>
#include <ctime>
#include <string>
@@ -95,7 +96,7 @@ namespace {
t_rpc_command_executor::t_rpc_command_executor(
uint32_t ip
, uint16_t port
- , const std::string &user_agent
+ , const boost::optional<tools::login>& login
, bool is_rpc
, cryptonote::core_rpc_server* rpc_server
)
@@ -103,7 +104,10 @@ t_rpc_command_executor::t_rpc_command_executor(
{
if (is_rpc)
{
- m_rpc_client = new tools::t_rpc_client(ip, port);
+ boost::optional<epee::net_utils::http::login> http_login{};
+ if (login)
+ http_login.emplace(login->username, login->password.password());
+ m_rpc_client = new tools::t_rpc_client(ip, port, std::move(http_login));
}
else
{
@@ -368,12 +372,12 @@ bool t_rpc_command_executor::show_status() {
std::time_t uptime = std::time(nullptr) - ires.start_time;
- tools::success_msg_writer() << boost::format("Height: %llu/%llu (%.1f%%) on %s, %s, net hash %s, v%u%s, %s, %u+%u connections, uptime %ud %uh %um %us")
+ tools::success_msg_writer() << boost::format("Height: %llu/%llu (%.1f%%) on %s, %s, net hash %s, v%u%s, %s, %u(out)+%u(in) connections, uptime %ud %uh %um %us")
% (unsigned long long)ires.height
% (unsigned long long)(ires.target_height >= ires.height ? ires.target_height : ires.height)
% get_sync_percentage(ires)
% (ires.testnet ? "testnet" : "mainnet")
- % (mining_busy ? "syncing" : mres.active ? "mining at " + get_mining_speed(mres.speed) : "not mining")
+ % (mining_busy ? "syncing" : mres.active ? ( ( mres.is_background_mining_enabled ? "smart " : "" ) + std::string("mining at ") + get_mining_speed(mres.speed) ) : "not mining")
% get_mining_speed(ires.difficulty / ires.target)
% (unsigned)hfres.version
% get_fork_extra_info(hfres.earliest_height, ires.height, ires.target)
@@ -925,11 +929,12 @@ bool t_rpc_command_executor::print_transaction_pool_stats() {
return true;
}
-bool t_rpc_command_executor::start_mining(cryptonote::account_public_address address, uint64_t num_threads, bool testnet) {
+bool t_rpc_command_executor::start_mining(cryptonote::account_public_address address, uint64_t num_threads, bool testnet, bool do_background_mining = false) {
cryptonote::COMMAND_RPC_START_MINING::request req;
cryptonote::COMMAND_RPC_START_MINING::response res;
req.miner_address = cryptonote::get_account_address_as_str(testnet, address);
req.threads_count = num_threads;
+ req.do_background_mining = do_background_mining;
std::string fail_message = "Mining did not start";
diff --git a/src/daemon/rpc_command_executor.h b/src/daemon/rpc_command_executor.h
index afcd99d32..5b7b76448 100644
--- a/src/daemon/rpc_command_executor.h
+++ b/src/daemon/rpc_command_executor.h
@@ -38,6 +38,9 @@
#pragma once
+#include <boost/optional/optional_fwd.hpp>
+
+#include "common/common_fwd.h"
#include "common/rpc_client.h"
#include "misc_log_ex.h"
#include "cryptonote_core/cryptonote_core.h"
@@ -60,7 +63,7 @@ public:
t_rpc_command_executor(
uint32_t ip
, uint16_t port
- , const std::string &user_agent
+ , const boost::optional<tools::login>& user
, bool is_rpc = true
, cryptonote::core_rpc_server* rpc_server = NULL
);
@@ -103,7 +106,7 @@ public:
bool print_transaction_pool_stats();
- bool start_mining(cryptonote::account_public_address address, uint64_t num_threads, bool testnet);
+ bool start_mining(cryptonote::account_public_address address, uint64_t num_threads, bool testnet, bool do_background_mining);
bool stop_mining();
diff --git a/src/mnemonics/CMakeLists.txt b/src/mnemonics/CMakeLists.txt
index 936c43b99..6fe88d828 100644
--- a/src/mnemonics/CMakeLists.txt
+++ b/src/mnemonics/CMakeLists.txt
@@ -51,5 +51,7 @@ monero_add_library(mnemonics
${mnemonics_headers}
${mnemonics_private_headers})
target_link_libraries(mnemonics
+ PUBLIC
+ ${Boost_SYSTEM_LIBRARY}
PRIVATE
${EXTRA_LIBRARIES})
diff --git a/src/p2p/CMakeLists.txt b/src/p2p/CMakeLists.txt
index b5b7d87ff..6ef008baf 100644
--- a/src/p2p/CMakeLists.txt
+++ b/src/p2p/CMakeLists.txt
@@ -38,6 +38,7 @@ source_group(p2p FILES ${P2P})
monero_add_library(p2p ${P2P})
target_link_libraries(p2p
PUBLIC
+ epee
${UPNP_LIBRARIES}
${Boost_CHRONO_LIBRARY}
${Boost_PROGRAM_OPTIONS_LIBRARY}
diff --git a/src/ringct/CMakeLists.txt b/src/ringct/CMakeLists.txt
index 334a7f350..e15af205a 100644
--- a/src/ringct/CMakeLists.txt
+++ b/src/ringct/CMakeLists.txt
@@ -49,5 +49,6 @@ target_link_libraries(ringct
PUBLIC
common
crypto
+ cryptonote_basic
PRIVATE
${EXTRA_LIBRARIES})
diff --git a/src/ringct/rctSigs.cpp b/src/ringct/rctSigs.cpp
index b8f3596e8..f64e7dd41 100644
--- a/src/ringct/rctSigs.cpp
+++ b/src/ringct/rctSigs.cpp
@@ -34,7 +34,7 @@
#include "common/thread_group.h"
#include "common/util.h"
#include "rctSigs.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
using namespace crypto;
using namespace std;
diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt
index 6df93cde1..d93307486 100644
--- a/src/rpc/CMakeLists.txt
+++ b/src/rpc/CMakeLists.txt
@@ -27,9 +27,11 @@
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
set(rpc_sources
- core_rpc_server.cpp)
+ core_rpc_server.cpp
+ rpc_args.cpp)
-set(rpc_headers)
+set(rpc_headers
+ rpc_args.h)
set(rpc_private_headers
core_rpc_server.h
@@ -44,9 +46,11 @@ monero_add_library(rpc
${rpc_private_headers})
target_link_libraries(rpc
PUBLIC
+ common
cryptonote_core
cryptonote_protocol
epee
+ ${Boost_REGEX_LIBRARY}
${Boost_THREAD_LIBRARY}
PRIVATE
${EXTRA_LIBRARIES})
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index b2e8e6716..1caf737ca 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -33,11 +33,12 @@ using namespace epee;
#include "core_rpc_server.h"
#include "common/command_line.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
-#include "cryptonote_core/account.h"
-#include "cryptonote_core/cryptonote_basic_impl.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
+#include "cryptonote_basic/account.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
#include "misc_language.h"
#include "crypto/hash.h"
+#include "rpc/rpc_args.h"
#include "core_rpc_server_error_codes.h"
#define MAX_RESTRICTED_FAKE_OUTS_COUNT 40
@@ -49,11 +50,10 @@ namespace cryptonote
//-----------------------------------------------------------------------------------
void core_rpc_server::init_options(boost::program_options::options_description& desc)
{
- command_line::add_arg(desc, arg_rpc_bind_ip);
command_line::add_arg(desc, arg_rpc_bind_port);
command_line::add_arg(desc, arg_testnet_rpc_bind_port);
command_line::add_arg(desc, arg_restricted_rpc);
- command_line::add_arg(desc, arg_user_agent);
+ cryptonote::rpc_args::init_options(desc);
}
//------------------------------------------------------------------------------------------------------------------------------
core_rpc_server::core_rpc_server(
@@ -64,29 +64,29 @@ namespace cryptonote
, m_p2p(p2p)
{}
//------------------------------------------------------------------------------------------------------------------------------
- bool core_rpc_server::handle_command_line(
+ bool core_rpc_server::init(
const boost::program_options::variables_map& vm
)
{
+ m_testnet = command_line::get_arg(vm, command_line::arg_testnet_on);
+ m_net_server.set_threads_prefix("RPC");
+
auto p2p_bind_arg = m_testnet ? arg_testnet_rpc_bind_port : arg_rpc_bind_port;
- m_bind_ip = command_line::get_arg(vm, arg_rpc_bind_ip);
- m_port = command_line::get_arg(vm, p2p_bind_arg);
+ auto rpc_config = cryptonote::rpc_args::process(vm);
+ if (!rpc_config)
+ return false;
+
m_restricted = command_line::get_arg(vm, arg_restricted_rpc);
- return true;
- }
- //------------------------------------------------------------------------------------------------------------------------------
- bool core_rpc_server::init(
- const boost::program_options::variables_map& vm
- )
- {
- m_testnet = command_line::get_arg(vm, command_line::arg_testnet_on);
- std::string m_user_agent = command_line::get_arg(vm, command_line::arg_user_agent);
- m_net_server.set_threads_prefix("RPC");
- bool r = handle_command_line(vm);
- CHECK_AND_ASSERT_MES(r, false, "Failed to process command line in core_rpc_server");
- return epee::http_server_impl_base<core_rpc_server, connection_context>::init(m_port, m_bind_ip, m_user_agent);
+ boost::optional<epee::net_utils::http::login> http_login{};
+ std::string port = command_line::get_arg(vm, p2p_bind_arg);
+ if (rpc_config->login)
+ http_login.emplace(std::move(rpc_config->login->username), std::move(rpc_config->login->password).password());
+
+ return epee::http_server_impl_base<core_rpc_server, connection_context>::init(
+ std::move(port), std::move(rpc_config->bind_ip), std::move(http_login)
+ );
}
//------------------------------------------------------------------------------------------------------------------------------
bool core_rpc_server::check_core_busy()
@@ -635,7 +635,7 @@ namespace cryptonote
boost::thread::attributes attrs;
attrs.set_stack_size(THREAD_STACK_SIZE);
- if(!m_core.get_miner().start(adr, static_cast<size_t>(req.threads_count), attrs))
+ if(!m_core.get_miner().start(adr, static_cast<size_t>(req.threads_count), attrs, req.do_background_mining))
{
res.status = "Failed, mining not started";
LOG_PRINT_L0(res.status);
@@ -663,6 +663,7 @@ namespace cryptonote
const miner& lMiner = m_core.get_miner();
res.active = lMiner.is_mining();
+ res.is_background_mining_enabled = lMiner.get_is_background_mining_enabled();
if ( lMiner.is_mining() ) {
res.speed = lMiner.get_speed();
@@ -1446,12 +1447,6 @@ namespace cryptonote
}
//------------------------------------------------------------------------------------------------------------------------------
- const command_line::arg_descriptor<std::string> core_rpc_server::arg_rpc_bind_ip = {
- "rpc-bind-ip"
- , "IP for RPC server"
- , "127.0.0.1"
- };
-
const command_line::arg_descriptor<std::string> core_rpc_server::arg_rpc_bind_port = {
"rpc-bind-port"
, "Port for RPC server"
@@ -1469,11 +1464,4 @@ namespace cryptonote
, "Restrict RPC to view only commands"
, false
};
-
- const command_line::arg_descriptor<std::string> core_rpc_server::arg_user_agent = {
- "user-agent"
- , "Restrict RPC to clients using this user agent"
- , ""
- };
-
} // namespace cryptonote
diff --git a/src/rpc/core_rpc_server.h b/src/rpc/core_rpc_server.h
index 767bcc715..0421511a2 100644
--- a/src/rpc/core_rpc_server.h
+++ b/src/rpc/core_rpc_server.h
@@ -52,11 +52,9 @@ namespace cryptonote
{
public:
- static const command_line::arg_descriptor<std::string> arg_rpc_bind_ip;
static const command_line::arg_descriptor<std::string> arg_rpc_bind_port;
static const command_line::arg_descriptor<std::string> arg_testnet_rpc_bind_port;
static const command_line::arg_descriptor<bool> arg_restricted_rpc;
- static const command_line::arg_descriptor<std::string> arg_user_agent;
typedef epee::net_utils::connection_context_base connection_context;
@@ -175,10 +173,6 @@ namespace cryptonote
//-----------------------
private:
-
- bool handle_command_line(
- const boost::program_options::variables_map& vm
- );
bool check_core_busy();
bool check_core_ready();
@@ -188,8 +182,6 @@ private:
core& m_core;
nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<cryptonote::core> >& m_p2p;
- std::string m_port;
- std::string m_bind_ip;
bool m_testnet;
bool m_restricted;
};
diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h
index 0fc230d11..3ab1ea175 100644
--- a/src/rpc/core_rpc_server_commands_defs.h
+++ b/src/rpc/core_rpc_server_commands_defs.h
@@ -30,8 +30,8 @@
#pragma once
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
-#include "cryptonote_core/cryptonote_basic.h"
-#include "cryptonote_core/difficulty.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+#include "cryptonote_basic/difficulty.h"
#include "crypto/hash.h"
namespace cryptonote
@@ -500,10 +500,12 @@ namespace cryptonote
{
std::string miner_address;
uint64_t threads_count;
+ bool do_background_mining;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(miner_address)
KV_SERIALIZE(threads_count)
+ KV_SERIALIZE(do_background_mining)
END_KV_SERIALIZE_MAP()
};
@@ -608,6 +610,7 @@ namespace cryptonote
uint64_t speed;
uint32_t threads_count;
std::string address;
+ bool is_background_mining_enabled;
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE(status)
@@ -615,6 +618,7 @@ namespace cryptonote
KV_SERIALIZE(speed)
KV_SERIALIZE(threads_count)
KV_SERIALIZE(address)
+ KV_SERIALIZE(is_background_mining_enabled)
END_KV_SERIALIZE_MAP()
};
};
diff --git a/src/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp
new file mode 100644
index 000000000..79f3f7e12
--- /dev/null
+++ b/src/rpc/rpc_args.cpp
@@ -0,0 +1,96 @@
+// Copyright (c) 2014-2017, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+#include "rpc_args.h"
+
+#include <boost/asio/ip/address.hpp>
+#include "common/command_line.h"
+#include "common/i18n.h"
+
+namespace cryptonote
+{
+ rpc_args::descriptors::descriptors()
+ : rpc_bind_ip({"rpc-bind-ip", rpc_args::tr("Specify ip to bind rpc server"), "127.0.0.1"})
+ , rpc_login({"rpc-login", rpc_args::tr("Specify username[:password] required for RPC server"), "", true})
+ , confirm_external_bind({"confirm-external-bind", rpc_args::tr("Confirm rcp-bind-ip value is NOT a loopback (local) IP")})
+ {}
+
+ const char* rpc_args::tr(const char* str) { return i18n_translate(str, "cryptonote::rpc_args"); }
+
+ void rpc_args::init_options(boost::program_options::options_description& desc)
+ {
+ const descriptors arg{};
+ command_line::add_arg(desc, arg.rpc_bind_ip);
+ command_line::add_arg(desc, arg.rpc_login);
+ command_line::add_arg(desc, arg.confirm_external_bind);
+ }
+
+ boost::optional<rpc_args> rpc_args::process(const boost::program_options::variables_map& vm)
+ {
+ const descriptors arg{};
+ rpc_args config{};
+
+ config.bind_ip = command_line::get_arg(vm, arg.rpc_bind_ip);
+ if (!config.bind_ip.empty())
+ {
+ // always parse IP here for error consistency
+ boost::system::error_code ec{};
+ const auto parsed_ip = boost::asio::ip::address::from_string(config.bind_ip, ec);
+ if (ec)
+ {
+ LOG_ERROR(tr("Invalid IP address given for --") << arg.rpc_bind_ip.name);
+ return boost::none;
+ }
+
+ if (!parsed_ip.is_loopback() && !command_line::get_arg(vm, arg.confirm_external_bind))
+ {
+ LOG_ERROR(
+ "--" << arg.rpc_bind_ip.name <<
+ tr(" permits inbound unencrypted external connections. Consider SSH tunnel or SSL proxy instead. Override with --") <<
+ arg.confirm_external_bind.name
+ );
+ return boost::none;
+ }
+ }
+
+ if (command_line::has_arg(vm, arg.rpc_login))
+ {
+ config.login = tools::login::parse(command_line::get_arg(vm, arg.rpc_login), true, "RPC server password");
+ if (!config.login)
+ return boost::none;
+
+ if (config.login->username.empty())
+ {
+ LOG_ERROR(tr("Username specified with --") << arg.rpc_login.name << tr(" cannot be empty"));
+ return boost::none;
+ }
+ }
+
+ return {std::move(config)};
+ }
+}
diff --git a/src/rpc/rpc_args.h b/src/rpc/rpc_args.h
new file mode 100644
index 000000000..d6e7bab07
--- /dev/null
+++ b/src/rpc/rpc_args.h
@@ -0,0 +1,67 @@
+// Copyright (c) 2014-2017, The Monero Project
+//
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without modification, are
+// permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this list of
+// conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice, this list
+// of conditions and the following disclaimer in the documentation and/or other
+// materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its contributors may be
+// used to endorse or promote products derived from this software without specific
+// prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
+// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+#pragma once
+
+#include <boost/optional/optional.hpp>
+#include <boost/program_options/options_description.hpp>
+#include <boost/program_options/variables_map.hpp>
+#include <string>
+
+#include "common/command_line.h"
+#include "common/password.h"
+
+namespace cryptonote
+{
+ //! Processes command line arguments related to server-side RPC
+ struct rpc_args
+ {
+ // non-static construction prevents initialization order issues
+ struct descriptors
+ {
+ descriptors();
+ descriptors(const descriptors&) = delete;
+ descriptors(descriptors&&) = delete;
+ descriptors& operator=(const descriptors&) = delete;
+ descriptors& operator=(descriptors&&) = delete;
+
+ const command_line::arg_descriptor<std::string> rpc_bind_ip;
+ const command_line::arg_descriptor<std::string> rpc_login;
+ const command_line::arg_descriptor<bool> confirm_external_bind;
+ };
+
+ static const char* tr(const char* str);
+ static void init_options(boost::program_options::options_description& desc);
+
+ //! \return Arguments specified by user, or `boost::none` if error
+ static boost::optional<rpc_args> process(const boost::program_options::variables_map& vm);
+
+ std::string bind_ip;
+ boost::optional<tools::login> login; // currently `boost::none` if unspecified by user
+ };
+}
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index a8f1d177f..41665e4d8 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -50,7 +50,7 @@
#include "p2p/net_node.h"
#include "cryptonote_protocol/cryptonote_protocol_handler.h"
#include "simplewallet.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
#include "storages/http_abstract_invoke.h"
#include "rpc/core_rpc_server_commands_defs.h"
#include "crypto/crypto.h" // for crypto::secret_key definition
@@ -1192,7 +1192,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
}
catch (const std::exception &e) { }
- m_http_client.set_server(m_wallet->get_daemon_address());
+ m_http_client.set_server(m_wallet->get_daemon_address(), m_wallet->get_daemon_login());
m_wallet->callback(this);
return true;
}
@@ -2175,7 +2175,10 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
bool has_payment_id;
crypto::hash8 new_payment_id;
if (!cryptonote::get_account_address_from_str_or_url(de.addr, has_payment_id, new_payment_id, m_wallet->testnet(), local_args[i]))
+ {
+ fail_msg_writer() << tr("failed to parse address");
return true;
+ }
if (has_payment_id)
{
@@ -2670,7 +2673,10 @@ bool simple_wallet::sweep_all(const std::vector<std::string> &args_)
crypto::hash8 new_payment_id;
cryptonote::account_public_address address;
if (!cryptonote::get_account_address_from_str_or_url(address, has_payment_id, new_payment_id, m_wallet->testnet(), local_args[0]))
+ {
+ fail_msg_writer() << tr("failed to parse address");
return true;
+ }
if (has_payment_id)
{
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
index ce0a24be7..efa748b0d 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -40,11 +40,11 @@
#include <boost/optional/optional.hpp>
#include <boost/program_options/variables_map.hpp>
-#include "cryptonote_core/account.h"
-#include "cryptonote_core/cryptonote_basic_impl.h"
+#include "cryptonote_basic/account.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
#include "wallet/wallet2.h"
#include "console_handler.h"
-#include "wallet/password_container.h"
+#include "common/password.h"
#include "crypto/crypto.h" // for definition of crypto::secret_key
#undef MONERO_DEFAULT_LOG_CATEGORY
diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt
index 922464a3c..8626001ce 100644
--- a/src/wallet/CMakeLists.txt
+++ b/src/wallet/CMakeLists.txt
@@ -31,7 +31,6 @@
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(wallet_sources
- password_container.cpp
wallet2.cpp
wallet_args.cpp
node_rpc_proxy.cpp
@@ -49,7 +48,6 @@ set(wallet_api_headers
set(wallet_private_headers
- password_container.h
wallet2.h
wallet_args.h
wallet_errors.h
@@ -74,6 +72,7 @@ monero_add_library(wallet
${wallet_private_headers})
target_link_libraries(wallet
PUBLIC
+ common
cryptonote_core
mnemonics
p2p
diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp
index 760c84f4f..09010a688 100644
--- a/src/wallet/api/pending_transaction.cpp
+++ b/src/wallet/api/pending_transaction.cpp
@@ -32,9 +32,8 @@
#include "wallet.h"
#include "common_defines.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
-#include "cryptonote_core/cryptonote_basic_impl.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
#include <memory>
#include <vector>
diff --git a/src/wallet/api/unsigned_transaction.cpp b/src/wallet/api/unsigned_transaction.cpp
index 84ec2d9d2..b412084b0 100644
--- a/src/wallet/api/unsigned_transaction.cpp
+++ b/src/wallet/api/unsigned_transaction.cpp
@@ -32,9 +32,8 @@
#include "wallet.h"
#include "common_defines.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
-#include "cryptonote_core/cryptonote_basic_impl.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
#include <memory>
#include <vector>
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 830f98909..c46de6b06 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -44,6 +44,9 @@
using namespace std;
using namespace cryptonote;
+#undef MONERO_DEFAULT_LOG_CATEGORY
+#define MONERO_DEFAULT_LOG_CATEGORY "WalletAPI"
+
namespace Monero {
namespace {
@@ -255,6 +258,9 @@ uint64_t Wallet::maximumAllowedAmount()
return std::numeric_limits<uint64_t>::max();
}
+void Wallet::debug(const std::string &str) {
+ MDEBUG(str);
+}
///////////////////////// WalletImpl implementation ////////////////////////
WalletImpl::WalletImpl(bool testnet)
@@ -1354,7 +1360,7 @@ bool WalletImpl::isNewWallet() const
bool WalletImpl::doInit(const string &daemon_address, uint64_t upper_transaction_size_limit)
{
- if (!m_wallet->init(daemon_address, upper_transaction_size_limit))
+ if (!m_wallet->init(daemon_address, boost::none, upper_transaction_size_limit))
return false;
// in case new wallet, this will force fast-refresh (pulling hashes instead of blocks)
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
index c761cc6d2..4104e7884 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -48,7 +48,7 @@ namespace {
bool connect_and_invoke(const std::string& address, const std::string& path, const Request& request, Response& response)
{
epee::net_utils::http::http_simple_client client{};
- return client.set_server(address) && epee::net_utils::invoke_http_json(path, request, response, client);
+ return client.set_server(address, boost::none) && epee::net_utils::invoke_http_json(path, request, response, client);
}
}
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index c52281a2b..e7a175dc7 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -39,10 +39,10 @@ using namespace epee;
#include "cryptonote_config.h"
#include "wallet2.h"
#include "wallet2_api.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
#include "rpc/core_rpc_server_commands_defs.h"
#include "misc_language.h"
-#include "cryptonote_core/cryptonote_basic_impl.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
#include "common/boost_serialization_helper.h"
#include "common/command_line.h"
#include "profile_tools.h"
@@ -108,6 +108,7 @@ struct options {
const command_line::arg_descriptor<std::string> password = {"password", tools::wallet2::tr("Wallet password"), "", true};
const command_line::arg_descriptor<std::string> password_file = {"password-file", tools::wallet2::tr("Wallet password file"), "", true};
const command_line::arg_descriptor<int> daemon_port = {"daemon-port", tools::wallet2::tr("Use daemon instance at port <arg> instead of 18081"), 0};
+ const command_line::arg_descriptor<std::string> daemon_login = {"daemon-login", tools::wallet2::tr("Specify username[:password] for daemon RPC client"), "", true};
const command_line::arg_descriptor<bool> testnet = {"testnet", tools::wallet2::tr("For testnet. Daemon must also be launched with --testnet flag"), false};
const command_line::arg_descriptor<bool> restricted = {"restricted-rpc", tools::wallet2::tr("Restricts to view-only commands"), false};
};
@@ -152,6 +153,18 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
return nullptr;
}
+ boost::optional<epee::net_utils::http::login> login{};
+ if (command_line::has_arg(vm, opts.daemon_login))
+ {
+ auto parsed = tools::login::parse(
+ command_line::get_arg(vm, opts.daemon_login), false, "Daemon client password"
+ );
+ if (!parsed)
+ return nullptr;
+
+ login.emplace(std::move(parsed->username), std::move(parsed->password).password());
+ }
+
if (daemon_host.empty())
daemon_host = "localhost";
@@ -164,7 +177,7 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
daemon_address = std::string("http://") + daemon_host + ":" + std::to_string(daemon_port);
std::unique_ptr<tools::wallet2> wallet(new tools::wallet2(testnet, restricted));
- wallet->init(std::move(daemon_address));
+ wallet->init(std::move(daemon_address), std::move(login));
return wallet;
}
@@ -434,6 +447,7 @@ void wallet2::init_options(boost::program_options::options_description& desc_par
command_line::add_arg(desc_params, opts.password);
command_line::add_arg(desc_params, opts.password_file);
command_line::add_arg(desc_params, opts.daemon_port);
+ command_line::add_arg(desc_params, opts.daemon_login);
command_line::add_arg(desc_params, opts.testnet);
command_line::add_arg(desc_params, opts.restricted);
}
@@ -485,13 +499,14 @@ std::pair<std::unique_ptr<wallet2>, password_container> wallet2::make_new(const
}
//----------------------------------------------------------------------------------------------------
-bool wallet2::init(std::string daemon_address, uint64_t upper_transaction_size_limit)
+bool wallet2::init(std::string daemon_address, boost::optional<epee::net_utils::http::login> daemon_login, uint64_t upper_transaction_size_limit)
{
if(m_http_client.is_connected())
m_http_client.disconnect();
m_upper_transaction_size_limit = upper_transaction_size_limit;
m_daemon_address = std::move(daemon_address);
- return m_http_client.set_server(get_daemon_address());
+ m_daemon_login = std::move(daemon_login);
+ return m_http_client.set_server(get_daemon_address(), get_daemon_login());
}
//----------------------------------------------------------------------------------------------------
bool wallet2::is_deterministic() const
@@ -3315,7 +3330,7 @@ uint64_t wallet2::get_per_kb_fee()
// transactions will be required
std::vector<wallet2::pending_tx> wallet2::create_transactions(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t> extra, bool trusted_daemon)
{
- const std::vector<size_t> unused_transfers_indices = select_available_outputs_from_histogram(fake_outs_count + 1, true, true, trusted_daemon);
+ const std::vector<size_t> unused_transfers_indices = select_available_outputs_from_histogram(fake_outs_count + 1, true, true, true, trusted_daemon);
const bool use_new_fee = use_fork_rules(3, -720 * 14);
const uint64_t fee_per_kb = get_per_kb_fee();
@@ -4120,7 +4135,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
THROW_WALLET_EXCEPTION_IF(needed_money == 0, error::zero_destination);
// gather all our dust and non dust outputs
- const std::vector<size_t> unused_indices = select_available_outputs_from_histogram(fake_outs_count + 1, true, true, trusted_daemon);
+ const std::vector<size_t> unused_indices = select_available_outputs_from_histogram(fake_outs_count + 1, true, true, true, trusted_daemon);
for (size_t i: unused_indices)
{
const transfer_details& td = m_transfers[i];
@@ -4614,7 +4629,7 @@ std::vector<uint64_t> wallet2::get_unspent_amounts_vector()
for (const auto &td: m_transfers)
{
if (!td.m_spent)
- set.insert(td.amount());
+ set.insert(td.is_rct() ? 0 : td.amount());
}
std::vector<uint64_t> vector;
vector.reserve(set.size());
@@ -4625,7 +4640,7 @@ std::vector<uint64_t> wallet2::get_unspent_amounts_vector()
return vector;
}
//----------------------------------------------------------------------------------------------------
-std::vector<size_t> wallet2::select_available_outputs_from_histogram(uint64_t count, bool atleast, bool unlocked, bool trusted_daemon)
+std::vector<size_t> wallet2::select_available_outputs_from_histogram(uint64_t count, bool atleast, bool unlocked, bool allow_rct, bool trusted_daemon)
{
epee::json_rpc::request<cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::request> req_t = AUTO_VAL_INIT(req_t);
epee::json_rpc::response<cryptonote::COMMAND_RPC_GET_OUTPUT_HISTOGRAM::response, std::string> resp_t = AUTO_VAL_INIT(resp_t);
@@ -4640,7 +4655,7 @@ std::vector<size_t> wallet2::select_available_outputs_from_histogram(uint64_t co
req_t.params.unlocked = unlocked;
bool r = net_utils::invoke_http_json("/json_rpc", req_t, resp_t, m_http_client);
m_daemon_rpc_mutex.unlock();
- THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "select_available_unmixable_outputs");
+ THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "select_available_outputs_from_histogram");
THROW_WALLET_EXCEPTION_IF(resp_t.result.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "get_output_histogram");
THROW_WALLET_EXCEPTION_IF(resp_t.result.status != CORE_RPC_STATUS_OK, error::get_histogram_error, resp_t.result.status);
@@ -4650,10 +4665,10 @@ std::vector<size_t> wallet2::select_available_outputs_from_histogram(uint64_t co
mixable.insert(i.amount);
}
- return select_available_outputs([mixable, atleast](const transfer_details &td) {
- if (td.is_rct())
+ return select_available_outputs([mixable, atleast, allow_rct](const transfer_details &td) {
+ if (!allow_rct && td.is_rct())
return false;
- const uint64_t amount = td.amount();
+ const uint64_t amount = td.is_rct() ? 0 : td.amount();
if (atleast) {
if (mixable.find(amount) != mixable.end())
return true;
@@ -4698,14 +4713,14 @@ std::vector<size_t> wallet2::select_available_unmixable_outputs(bool trusted_dae
{
// request all outputs with less than 3 instances
const size_t min_mixin = use_fork_rules(5, 10) ? 4 : 2; // v5 increases min mixin from 2 to 4
- return select_available_outputs_from_histogram(min_mixin + 1, false, true, trusted_daemon);
+ return select_available_outputs_from_histogram(min_mixin + 1, false, true, false, trusted_daemon);
}
//----------------------------------------------------------------------------------------------------
std::vector<size_t> wallet2::select_available_mixable_outputs(bool trusted_daemon)
{
// request all outputs with at least 3 instances, so we can use mixin 2 with
const size_t min_mixin = use_fork_rules(5, 10) ? 4 : 2; // v5 increases min mixin from 2 to 4
- return select_available_outputs_from_histogram(min_mixin + 1, true, true, trusted_daemon);
+ return select_available_outputs_from_histogram(min_mixin + 1, true, true, true, trusted_daemon);
}
//----------------------------------------------------------------------------------------------------
std::vector<wallet2::pending_tx> wallet2::create_unmixable_sweep_transactions(bool trusted_daemon)
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 567292d30..dba9a400d 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -39,13 +39,14 @@
#include <atomic>
#include "include_base_utils.h"
-#include "cryptonote_core/account.h"
-#include "cryptonote_core/account_boost_serialization.h"
-#include "cryptonote_core/cryptonote_basic_impl.h"
+#include "cryptonote_basic/account.h"
+#include "cryptonote_basic/account_boost_serialization.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
#include "net/http_client.h"
#include "storages/http_abstract_invoke.h"
#include "rpc/core_rpc_server_commands_defs.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
+#include "cryptonote_core/cryptonote_tx_utils.h"
#include "common/unordered_containers_boost_serialization.h"
#include "crypto/chacha8.h"
#include "crypto/hash.h"
@@ -53,7 +54,7 @@
#include "ringct/rctOps.h"
#include "wallet_errors.h"
-#include "password_container.h"
+#include "common/password.h"
#include "node_rpc_proxy.h"
#include <iostream>
@@ -343,7 +344,8 @@ namespace tools
// into account the current median block size rather than
// the minimum block size.
bool deinit();
- bool init(std::string daemon_address = "http://localhost:8080", uint64_t upper_transaction_size_limit = 0);
+ bool init(std::string daemon_address = "http://localhost:8080",
+ boost::optional<epee::net_utils::http::login> daemon_login = boost::none, uint64_t upper_transaction_size_limit = 0);
void stop() { m_run.store(false, std::memory_order_relaxed); }
@@ -527,13 +529,14 @@ namespace tools
std::string get_wallet_file() const;
std::string get_keys_file() const;
std::string get_daemon_address() const;
+ const boost::optional<epee::net_utils::http::login>& get_daemon_login() const { return m_daemon_login; }
uint64_t get_daemon_blockchain_height(std::string& err);
uint64_t get_daemon_blockchain_target_height(std::string& err);
/*!
* \brief Calculates the approximate blockchain height from current date/time.
*/
uint64_t get_approximate_blockchain_height() const;
- std::vector<size_t> select_available_outputs_from_histogram(uint64_t count, bool atleast, bool unlocked, bool trusted_daemon);
+ std::vector<size_t> select_available_outputs_from_histogram(uint64_t count, bool atleast, bool unlocked, bool allow_rct, bool trusted_daemon);
std::vector<size_t> select_available_outputs(const std::function<bool(const transfer_details &td)> &f);
std::vector<size_t> select_available_unmixable_outputs(bool trusted_daemon);
std::vector<size_t> select_available_mixable_outputs(bool trusted_daemon);
@@ -619,6 +622,7 @@ namespace tools
crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const;
cryptonote::account_base m_account;
+ boost::optional<epee::net_utils::http::login> m_daemon_login;
std::string m_daemon_address;
std::string m_wallet_file;
std::string m_keys_file;
diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h
index 883da7da2..daa3deeee 100644
--- a/src/wallet/wallet2_api.h
+++ b/src/wallet/wallet2_api.h
@@ -428,6 +428,8 @@ struct Wallet
static bool keyValid(const std::string &secret_key_string, const std::string &address_string, bool isViewKey, bool testnet, std::string &error);
static std::string paymentIdFromAddress(const std::string &str, bool testnet);
static uint64_t maximumAllowedAmount();
+ // Easylogger wrapper
+ static void debug(const std::string &str);
/**
* @brief StartRefresh - Start/resume refresh thread (refresh every 10 seconds)
diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h
index 785a72e4b..fc0471be7 100644
--- a/src/wallet/wallet_errors.h
+++ b/src/wallet/wallet_errors.h
@@ -35,7 +35,7 @@
#include <string>
#include <vector>
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
#include "rpc/core_rpc_server_commands_defs.h"
#include "include_base_utils.h"
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 22f5f8bb6..881279e42 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -38,13 +38,14 @@ using namespace epee;
#include "common/command_line.h"
#include "common/i18n.h"
#include "common/util.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
-#include "cryptonote_core/account.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
+#include "cryptonote_basic/account.h"
#include "wallet_rpc_server_commands_defs.h"
#include "misc_language.h"
#include "string_coding.h"
#include "string_tools.h"
#include "crypto/hash.h"
+#include "rpc/rpc_args.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.rpc"
@@ -52,10 +53,7 @@ using namespace epee;
namespace
{
const command_line::arg_descriptor<std::string, true> arg_rpc_bind_port = {"rpc-bind-port", "Sets bind port for server"};
- const command_line::arg_descriptor<std::string> arg_rpc_bind_ip = {"rpc-bind-ip", "Specify ip to bind rpc server", "127.0.0.1"};
- const command_line::arg_descriptor<std::string> arg_rpc_login = {"rpc-login", "Specify username[:password] required for RPC connection"};
- const command_line::arg_descriptor<bool> arg_disable_rpc_login = {"disable-rpc-login", "Disable HTTP authentication for RPC"};
- const command_line::arg_descriptor<bool> arg_confirm_external_bind = {"confirm-external-bind", "Confirm rcp-bind-ip value is NOT a loopback (local) IP"};
+ const command_line::arg_descriptor<bool> arg_disable_rpc_login = {"disable-rpc-login", "Disable HTTP authentication for RPC connections served by this process"};
constexpr const char default_rpc_username[] = "monero";
}
@@ -107,75 +105,41 @@ namespace tools
//------------------------------------------------------------------------------------------------------------------------------
bool wallet_rpc_server::init(const boost::program_options::variables_map& vm)
{
- std::string bind_ip = command_line::get_arg(vm, arg_rpc_bind_ip);
- if (!bind_ip.empty())
- {
- // always parse IP here for error consistency
- boost::system::error_code ec{};
- const auto parsed_ip = boost::asio::ip::address::from_string(bind_ip, ec);
- if (ec)
- {
- LOG_ERROR(tr("Invalid IP address given for rpc-bind-ip argument"));
- return false;
- }
-
- if (!parsed_ip.is_loopback() && !command_line::get_arg(vm, arg_confirm_external_bind))
- {
- LOG_ERROR(
- tr("The rpc-bind-ip value is listening for unencrypted external connections. Consider SSH tunnel or SSL proxy instead. Override with --confirm-external-bind")
- );
- return false;
- }
- }
-
- epee::net_utils::http::login login{};
+ auto rpc_config = cryptonote::rpc_args::process(vm);
+ if (!rpc_config)
+ return false;
+ boost::optional<epee::net_utils::http::login> http_login{};
+ std::string bind_port = command_line::get_arg(vm, arg_rpc_bind_port);
const bool disable_auth = command_line::get_arg(vm, arg_disable_rpc_login);
- const std::string user_pass = command_line::get_arg(vm, arg_rpc_login);
- const std::string bind_port = command_line::get_arg(vm, arg_rpc_bind_port);
if (disable_auth)
{
- if (!user_pass.empty())
+ if (rpc_config->login)
{
- LOG_ERROR(tr("Cannot specify --") << arg_disable_rpc_login.name << tr(" and --") << arg_rpc_login.name);
+ const cryptonote::rpc_args::descriptors arg{};
+ LOG_ERROR(tr("Cannot specify --") << arg_disable_rpc_login.name << tr(" and --") << arg.rpc_login.name);
return false;
}
}
else // auth enabled
{
- if (user_pass.empty())
+ if (!rpc_config->login)
{
- login.username = default_rpc_username;
-
std::array<std::uint8_t, 16> rand_128bit{{}};
crypto::rand(rand_128bit.size(), rand_128bit.data());
- login.password = string_encoding::base64_encode(rand_128bit.data(), rand_128bit.size());
+ http_login.emplace(
+ default_rpc_username,
+ string_encoding::base64_encode(rand_128bit.data(), rand_128bit.size())
+ );
}
- else // user password
+ else
{
- const auto loc = user_pass.find(':');
- login.username = user_pass.substr(0, loc);
- if (loc != std::string::npos)
- {
- login.password = user_pass.substr(loc + 1);
- }
- else
- {
- login.password = tools::password_container::prompt(true, "RPC password").value_or(
- tools::password_container{}
- ).password();
- }
-
- if (login.username.empty() || login.password.empty())
- {
- LOG_ERROR(tr("Blank username or password not permitted for RPC authenticaion"));
- return false;
- }
+ http_login.emplace(
+ std::move(rpc_config->login->username), std::move(rpc_config->login->password).password()
+ );
}
-
- assert(!login.username.empty());
- assert(!login.password.empty());
+ assert(bool(http_login));
std::string temp = "monero-wallet-rpc." + bind_port + ".login";
const auto cookie = tools::create_private_file(temp);
@@ -186,9 +150,9 @@ namespace tools
}
rpc_login_filename.swap(temp); // nothrow guarantee destructor cleanup
temp = rpc_login_filename;
- std::fputs(login.username.c_str(), cookie.get());
+ std::fputs(http_login->username.c_str(), cookie.get());
std::fputc(':', cookie.get());
- std::fputs(login.password.c_str(), cookie.get());
+ std::fputs(http_login->password.c_str(), cookie.get());
std::fflush(cookie.get());
if (std::ferror(cookie.get()))
{
@@ -200,7 +164,7 @@ namespace tools
m_net_server.set_threads_prefix("RPC");
return epee::http_server_impl_base<wallet_rpc_server, connection_context>::init(
- std::move(bind_port), std::move(bind_ip), std::string{}, boost::make_optional(!disable_auth, std::move(login))
+ std::move(bind_port), std::move(rpc_config->bind_ip), std::move(http_login)
);
}
//------------------------------------------------------------------------------------------------------------------------------
@@ -1410,14 +1374,13 @@ int main(int argc, char** argv) {
po::options_description desc_params(wallet_args::tr("Wallet options"));
tools::wallet2::init_options(desc_params);
- command_line::add_arg(desc_params, arg_rpc_bind_ip);
command_line::add_arg(desc_params, arg_rpc_bind_port);
- command_line::add_arg(desc_params, arg_rpc_login);
command_line::add_arg(desc_params, arg_disable_rpc_login);
- command_line::add_arg(desc_params, arg_confirm_external_bind);
+ cryptonote::rpc_args::init_options(desc_params);
command_line::add_arg(desc_params, arg_wallet_file);
command_line::add_arg(desc_params, arg_from_json);
+
const auto vm = wallet_args::main(
argc, argv,
"monero-wallet-rpc [--wallet-file=<file>|--generate-from-json=<file>] [--rpc-bind-port=<port>]",
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index e132b4e2b..86f37c658 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -30,7 +30,7 @@
#pragma once
#include "cryptonote_protocol/cryptonote_protocol_defs.h"
-#include "cryptonote_core/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic.h"
#include "crypto/hash.h"
#include "wallet_rpc_server_error_codes.h"
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 60b7a4dba..b3c40799e 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -43,24 +43,30 @@ if (GTest_FOUND)
include_directories(SYSTEM ${GTEST_INCLUDE_DIRS})
else ()
message(STATUS "GTest not found on the system: will use GTest bundled with this source")
- add_subdirectory(gtest)
- include_directories(SYSTEM "${gtest_SOURCE_DIR}/include" "${gtest_SOURCE_DIR}")
- # Emulate the FindGTest module's variable.
- set(GTEST_LIBRARIES gtest)
-
- # Ignore some warnings when building gtest binaries.
- if(NOT MSVC)
- set_property(TARGET gtest
- APPEND_STRING
- PROPERTY
- COMPILE_FLAGS " -Wno-undef -Wno-sign-compare")
- endif()
+ include(ExternalProject)
+ ExternalProject_Add(googletest
+ SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/gtest
+ BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/gtest
+ DOWNLOAD_COMMAND ""
+ UPDATE_COMMAND ""
+ INSTALL_COMMAND ""
+ )
+ add_library(gtest UNKNOWN IMPORTED)
+ add_library(gtest_main UNKNOWN IMPORTED)
+ set_target_properties(gtest PROPERTIES
+ IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/gtest/${CMAKE_STATIC_LIBRARY_PREFIX}gtest${CMAKE_STATIC_LIBRARY_SUFFIX}"
+ )
+ set_target_properties(gtest_main PROPERTIES
+ IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/gtest/${CMAKE_STATIC_LIBRARY_PREFIX}gtest_main${CMAKE_STATIC_LIBRARY_SUFFIX}"
+ )
+ add_dependencies(gtest googletest)
+ add_dependencies(gtest_main googletest)
- set_property(TARGET gtest
- PROPERTY
- FOLDER "${folder}")
-endif ()
+ # Emulate the FindGTest module's variable.
+ set(GTEST_LIBRARIES gtest gtest_main)
+ include_directories(SYSTEM "${CMAKE_CURRENT_SOURCE_DIR}/gtest/include")
+endif (GTest_FOUND)
file(COPY
data/wallet_9svHk1.keys
diff --git a/tests/core_proxy/core_proxy.h b/tests/core_proxy/core_proxy.h
index bec9a83bb..c649f51cc 100644
--- a/tests/core_proxy/core_proxy.h
+++ b/tests/core_proxy/core_proxy.h
@@ -32,8 +32,8 @@
#include <boost/program_options/variables_map.hpp>
-#include "cryptonote_core/cryptonote_basic_impl.h"
-#include "cryptonote_core/verification_context.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
+#include "cryptonote_basic/verification_context.h"
#include <unordered_map>
namespace tests
diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp
index 4cb70e745..53d0872dd 100644
--- a/tests/core_tests/chaingen.cpp
+++ b/tests/core_tests/chaingen.cpp
@@ -37,10 +37,10 @@
#include "console_handler.h"
#include "p2p/net_node.h"
-#include "cryptonote_core/cryptonote_basic.h"
-#include "cryptonote_core/cryptonote_basic_impl.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
-#include "cryptonote_core/miner.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
+#include "cryptonote_basic/miner.h"
#include "chaingen.h"
diff --git a/tests/core_tests/chaingen.h b/tests/core_tests/chaingen.h
index 04f910efc..4b0ed1355 100644
--- a/tests/core_tests/chaingen.h
+++ b/tests/core_tests/chaingen.h
@@ -44,12 +44,12 @@
#include "common/boost_serialization_helper.h"
#include "common/command_line.h"
-#include "cryptonote_core/account_boost_serialization.h"
-#include "cryptonote_core/cryptonote_basic.h"
-#include "cryptonote_core/cryptonote_basic_impl.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/account_boost_serialization.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
#include "cryptonote_core/cryptonote_core.h"
-#include "cryptonote_core/cryptonote_boost_serialization.h"
+#include "cryptonote_basic/cryptonote_boost_serialization.h"
#include "misc_language.h"
#undef MONERO_DEFAULT_LOG_CATEGORY
diff --git a/tests/core_tests/chaingen001.cpp b/tests/core_tests/chaingen001.cpp
index f5150f2f7..9abd97185 100644
--- a/tests/core_tests/chaingen001.cpp
+++ b/tests/core_tests/chaingen001.cpp
@@ -35,8 +35,8 @@
#include "console_handler.h"
-#include "cryptonote_core/cryptonote_basic.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
#include "chaingen.h"
#include "chaingen_tests_list.h"
diff --git a/tests/core_tests/transaction_tests.cpp b/tests/core_tests/transaction_tests.cpp
index cb585b975..b4af597e9 100644
--- a/tests/core_tests/transaction_tests.cpp
+++ b/tests/core_tests/transaction_tests.cpp
@@ -29,9 +29,9 @@
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "include_base_utils.h"
-#include "cryptonote_core/cryptonote_basic_impl.h"
-#include "cryptonote_core/account.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
+#include "cryptonote_basic/account.h"
+#include "cryptonote_core/cryptonote_tx_utils.h"
#include "misc_language.h"
using namespace cryptonote;
diff --git a/tests/daemon_tests/transfers.cpp b/tests/daemon_tests/transfers.cpp
index ea851c541..398fdefe9 100644
--- a/tests/daemon_tests/transfers.cpp
+++ b/tests/daemon_tests/transfers.cpp
@@ -32,7 +32,7 @@
#include <sstream>
#include "wallet/wallet.h"
#include "rpc/core_rpc_server.h"
-#include "cryptonote_core/account.h"
+#include "cryptonote_basic/account.h"
#include "net/http_client_abstract_invoke.h"
using namespace std;
using namespace epee::misc_utils;
diff --git a/tests/difficulty/difficulty.cpp b/tests/difficulty/difficulty.cpp
index edfce46ab..d4c8e94c8 100644
--- a/tests/difficulty/difficulty.cpp
+++ b/tests/difficulty/difficulty.cpp
@@ -36,7 +36,7 @@
#include <algorithm>
#include "cryptonote_config.h"
-#include "cryptonote_core/difficulty.h"
+#include "cryptonote_basic/difficulty.h"
using namespace std;
diff --git a/tests/functional_tests/transactions_flow_test.cpp b/tests/functional_tests/transactions_flow_test.cpp
index 5666f49bf..8e7e494c9 100644
--- a/tests/functional_tests/transactions_flow_test.cpp
+++ b/tests/functional_tests/transactions_flow_test.cpp
@@ -159,7 +159,7 @@ bool transactions_flow_test(std::string& working_folder,
epee::net_utils::http::http_simple_client http_client;
COMMAND_RPC_STOP_MINING::request daemon1_req = AUTO_VAL_INIT(daemon1_req);
COMMAND_RPC_STOP_MINING::response daemon1_rsp = AUTO_VAL_INIT(daemon1_rsp);
- bool r = http_client.set_server(daemon_addr_a) && net_utils::invoke_http_json("/stop_mine", daemon1_req, daemon1_rsp, http_client, std::chrono::seconds(10));
+ bool r = http_client.set_server(daemon_addr_a, boost::none) && net_utils::invoke_http_json("/stop_mine", daemon1_req, daemon1_rsp, http_client, std::chrono::seconds(10));
CHECK_AND_ASSERT_MES(r, false, "failed to stop mining");
COMMAND_RPC_START_MINING::request daemon_req = AUTO_VAL_INIT(daemon_req);
diff --git a/tests/hash-target.cpp b/tests/hash-target.cpp
index aeb6688bc..de3a8df2c 100644
--- a/tests/hash-target.cpp
+++ b/tests/hash-target.cpp
@@ -33,7 +33,7 @@
#include <cstring>
#include <limits>
#include "crypto/hash.h"
-#include "cryptonote_core/difficulty.h"
+#include "cryptonote_basic/difficulty.h"
using namespace std;
using cryptonote::check_hash;
diff --git a/tests/performance_tests/check_tx_signature.h b/tests/performance_tests/check_tx_signature.h
index fe595a4da..b2b2f4004 100644
--- a/tests/performance_tests/check_tx_signature.h
+++ b/tests/performance_tests/check_tx_signature.h
@@ -32,9 +32,9 @@
#include <vector>
-#include "cryptonote_core/account.h"
-#include "cryptonote_core/cryptonote_basic.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/account.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+#include "cryptonote_core/cryptonote_tx_utils.h"
#include "crypto/crypto.h"
#include "ringct/rctSigs.h"
diff --git a/tests/performance_tests/cn_slow_hash.h b/tests/performance_tests/cn_slow_hash.h
index 5492299cd..b646e5121 100644
--- a/tests/performance_tests/cn_slow_hash.h
+++ b/tests/performance_tests/cn_slow_hash.h
@@ -31,7 +31,7 @@
#pragma once
#include "crypto/crypto.h"
-#include "cryptonote_core/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic.h"
class test_cn_slow_hash
{
diff --git a/tests/performance_tests/construct_tx.h b/tests/performance_tests/construct_tx.h
index aef455eaa..2fe6d288d 100644
--- a/tests/performance_tests/construct_tx.h
+++ b/tests/performance_tests/construct_tx.h
@@ -30,9 +30,9 @@
#pragma once
-#include "cryptonote_core/account.h"
-#include "cryptonote_core/cryptonote_basic.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/account.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+#include "cryptonote_core/cryptonote_tx_utils.h"
#include "multi_tx_test_base.h"
diff --git a/tests/performance_tests/derive_public_key.h b/tests/performance_tests/derive_public_key.h
index 727dde000..559745ef9 100644
--- a/tests/performance_tests/derive_public_key.h
+++ b/tests/performance_tests/derive_public_key.h
@@ -31,7 +31,7 @@
#pragma once
#include "crypto/crypto.h"
-#include "cryptonote_core/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic.h"
#include "single_tx_test_base.h"
diff --git a/tests/performance_tests/derive_secret_key.h b/tests/performance_tests/derive_secret_key.h
index 94df93843..c7aed162e 100644
--- a/tests/performance_tests/derive_secret_key.h
+++ b/tests/performance_tests/derive_secret_key.h
@@ -31,7 +31,7 @@
#pragma once
#include "crypto/crypto.h"
-#include "cryptonote_core/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic.h"
#include "single_tx_test_base.h"
diff --git a/tests/performance_tests/ge_frombytes_vartime.h b/tests/performance_tests/ge_frombytes_vartime.h
index c815422f9..bf1785ab4 100644
--- a/tests/performance_tests/ge_frombytes_vartime.h
+++ b/tests/performance_tests/ge_frombytes_vartime.h
@@ -31,7 +31,7 @@
#pragma once
#include "crypto/crypto.h"
-#include "cryptonote_core/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic.h"
#include "single_tx_test_base.h"
diff --git a/tests/performance_tests/generate_key_derivation.h b/tests/performance_tests/generate_key_derivation.h
index 35f41ef89..3e6481bda 100644
--- a/tests/performance_tests/generate_key_derivation.h
+++ b/tests/performance_tests/generate_key_derivation.h
@@ -31,7 +31,7 @@
#pragma once
#include "crypto/crypto.h"
-#include "cryptonote_core/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic.h"
#include "single_tx_test_base.h"
diff --git a/tests/performance_tests/generate_key_image.h b/tests/performance_tests/generate_key_image.h
index fee987969..4a5fbb946 100644
--- a/tests/performance_tests/generate_key_image.h
+++ b/tests/performance_tests/generate_key_image.h
@@ -31,7 +31,7 @@
#pragma once
#include "crypto/crypto.h"
-#include "cryptonote_core/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic.h"
#include "single_tx_test_base.h"
diff --git a/tests/performance_tests/generate_key_image_helper.h b/tests/performance_tests/generate_key_image_helper.h
index 44f5c9d12..66c9a244b 100644
--- a/tests/performance_tests/generate_key_image_helper.h
+++ b/tests/performance_tests/generate_key_image_helper.h
@@ -30,9 +30,9 @@
#pragma once
-#include "cryptonote_core/account.h"
-#include "cryptonote_core/cryptonote_basic.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/account.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
#include "single_tx_test_base.h"
diff --git a/tests/performance_tests/generate_keypair.h b/tests/performance_tests/generate_keypair.h
index 4ba577e2a..4f9179318 100644
--- a/tests/performance_tests/generate_keypair.h
+++ b/tests/performance_tests/generate_keypair.h
@@ -31,7 +31,7 @@
#pragma once
#include "crypto/crypto.h"
-#include "cryptonote_core/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic.h"
class test_generate_keypair
{
diff --git a/tests/performance_tests/is_out_to_acc.h b/tests/performance_tests/is_out_to_acc.h
index 7f8645b87..6c7adfa51 100644
--- a/tests/performance_tests/is_out_to_acc.h
+++ b/tests/performance_tests/is_out_to_acc.h
@@ -30,9 +30,9 @@
#pragma once
-#include "cryptonote_core/account.h"
-#include "cryptonote_core/cryptonote_basic.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/account.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+#include "cryptonote_core/cryptonote_tx_utils.h"
#include "single_tx_test_base.h"
diff --git a/tests/performance_tests/multi_tx_test_base.h b/tests/performance_tests/multi_tx_test_base.h
index feabab022..ef5d277f1 100644
--- a/tests/performance_tests/multi_tx_test_base.h
+++ b/tests/performance_tests/multi_tx_test_base.h
@@ -32,9 +32,9 @@
#include <vector>
-#include "cryptonote_core/account.h"
-#include "cryptonote_core/cryptonote_basic.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/account.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+#include "cryptonote_core/cryptonote_tx_utils.h"
#include "crypto/crypto.h"
template<size_t a_ring_size>
diff --git a/tests/performance_tests/single_tx_test_base.h b/tests/performance_tests/single_tx_test_base.h
index c667b71b7..3d3f81bc7 100644
--- a/tests/performance_tests/single_tx_test_base.h
+++ b/tests/performance_tests/single_tx_test_base.h
@@ -30,9 +30,9 @@
#pragma once
-#include "cryptonote_core/account.h"
-#include "cryptonote_core/cryptonote_basic.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/account.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+#include "cryptonote_core/cryptonote_tx_utils.h"
class single_tx_test_base
{
diff --git a/tests/unit_tests/CMakeLists.txt b/tests/unit_tests/CMakeLists.txt
index 08c8213e4..e70ed1a24 100644
--- a/tests/unit_tests/CMakeLists.txt
+++ b/tests/unit_tests/CMakeLists.txt
@@ -42,14 +42,14 @@ set(unit_tests_sources
epee_levin_protocol_handler_async.cpp
fee.cpp
get_xtype_from_string.cpp
- http_auth.cpp
+ http.cpp
main.cpp
mnemonics.cpp
mul_div.cpp
parse_amount.cpp
serialization.cpp
slow_memmem.cpp
- test_format_utils.cpp
+ test_tx_utils.cpp
test_peerlist.cpp
test_protocol_pack.cpp
thread_group.cpp
diff --git a/tests/unit_tests/base58.cpp b/tests/unit_tests/base58.cpp
index 53f7f2673..d2c767956 100644
--- a/tests/unit_tests/base58.cpp
+++ b/tests/unit_tests/base58.cpp
@@ -33,7 +33,7 @@
#include <cstdint>
#include "common/base58.cpp"
-#include "cryptonote_core/cryptonote_basic_impl.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
#include "serialization/binary_utils.h"
using namespace tools;
diff --git a/tests/unit_tests/block_reward.cpp b/tests/unit_tests/block_reward.cpp
index 5d93c3084..f8a944770 100644
--- a/tests/unit_tests/block_reward.cpp
+++ b/tests/unit_tests/block_reward.cpp
@@ -30,7 +30,7 @@
#include "gtest/gtest.h"
-#include "cryptonote_core/cryptonote_basic_impl.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
using namespace cryptonote;
diff --git a/tests/unit_tests/blockchain_db.cpp b/tests/unit_tests/blockchain_db.cpp
index 127a15b44..8fc10be10 100644
--- a/tests/unit_tests/blockchain_db.cpp
+++ b/tests/unit_tests/blockchain_db.cpp
@@ -40,7 +40,7 @@
#ifdef BERKELEY_DB
#include "blockchain_db/berkeleydb/db_bdb.h"
#endif
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
using namespace cryptonote;
using epee::string_tools::pod_to_hex;
diff --git a/tests/unit_tests/canonical_amounts.cpp b/tests/unit_tests/canonical_amounts.cpp
index 9bef58d4b..c5a27d47d 100644
--- a/tests/unit_tests/canonical_amounts.cpp
+++ b/tests/unit_tests/canonical_amounts.cpp
@@ -29,7 +29,7 @@
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "gtest/gtest.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
static const uint64_t valid_decomposed_outputs[] = {
(uint64_t)1, (uint64_t)2, (uint64_t)3, (uint64_t)4, (uint64_t)5, (uint64_t)6, (uint64_t)7, (uint64_t)8, (uint64_t)9, // 1 piconero
diff --git a/tests/unit_tests/checkpoints.cpp b/tests/unit_tests/checkpoints.cpp
index b1d251d26..bc18c2b9e 100644
--- a/tests/unit_tests/checkpoints.cpp
+++ b/tests/unit_tests/checkpoints.cpp
@@ -30,7 +30,7 @@
#include "gtest/gtest.h"
-#include "cryptonote_core/checkpoints.cpp"
+#include "cryptonote_basic/checkpoints.cpp"
using namespace cryptonote;
diff --git a/tests/unit_tests/decompose_amount_into_digits.cpp b/tests/unit_tests/decompose_amount_into_digits.cpp
index e40208113..b1fa79aa1 100644
--- a/tests/unit_tests/decompose_amount_into_digits.cpp
+++ b/tests/unit_tests/decompose_amount_into_digits.cpp
@@ -33,7 +33,7 @@
#include <cstdint>
#include <vector>
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
#define VEC_FROM_ARR(vec) \
std::vector<uint64_t> vec; \
diff --git a/tests/unit_tests/hardfork.cpp b/tests/unit_tests/hardfork.cpp
index 2682f15d3..81cf32c8b 100644
--- a/tests/unit_tests/hardfork.cpp
+++ b/tests/unit_tests/hardfork.cpp
@@ -32,7 +32,7 @@
#include "gtest/gtest.h"
#include "blockchain_db/lmdb/db_lmdb.h"
-#include "cryptonote_core/hardfork.h"
+#include "cryptonote_basic/hardfork.h"
using namespace cryptonote;
diff --git a/tests/unit_tests/http_auth.cpp b/tests/unit_tests/http.cpp
index 97954642f..3513fa327 100644
--- a/tests/unit_tests/http_auth.cpp
+++ b/tests/unit_tests/http.cpp
@@ -109,7 +109,7 @@ http::http_response_info make_response(const auth_responses& choices)
std::string out{" DIGEST "};
write_fields(out, choice);
- response.m_additional_fields.push_back(
+ response.m_header_info.m_etc_fields.push_back(
std::make_pair(u8"WWW-authenticate", std::move(out))
);
}
@@ -510,7 +510,7 @@ TEST(HTTP_Server_Auth, MD5_sess_auth)
TEST(HTTP_Auth, DogFood)
{
- const auto add_field = [] (http::http_request_info& request, http::http_client_auth& client)
+ const auto add_auth_field = [] (http::http_request_info& request, http::http_client_auth& client)
{
auto field = client.get_auth_field(request.m_http_method_str, request.m_URI);
EXPECT_TRUE(bool(field));
@@ -529,19 +529,21 @@ TEST(HTTP_Auth, DogFood)
request.m_http_method_str = "GET";
request.m_URI = "/FOO";
- const auto response = server.get_response(request);
+ auto response = server.get_response(request);
ASSERT_TRUE(bool(response));
EXPECT_TRUE(is_unauthorized(*response));
+ EXPECT_TRUE(response->m_header_info.m_etc_fields.empty());
+ response->m_header_info.m_etc_fields = response->m_additional_fields;
EXPECT_EQ(http::http_client_auth::kSuccess, client.handle_401(*response));
- EXPECT_TRUE(add_field(request, client));
+ EXPECT_TRUE(add_auth_field(request, client));
EXPECT_FALSE(bool(server.get_response(request)));
for (unsigned i = 0; i < 1000; ++i)
{
request.m_http_method_str += std::to_string(i);
request.m_header_info.m_etc_fields.clear();
- EXPECT_TRUE(add_field(request, client));
+ EXPECT_TRUE(add_auth_field(request, client));
EXPECT_FALSE(bool(server.get_response(request)));
}
@@ -549,11 +551,13 @@ TEST(HTTP_Auth, DogFood)
request.m_header_info.m_etc_fields.clear();
client = http::http_client_auth{user};
EXPECT_EQ(http::http_client_auth::kSuccess, client.handle_401(*response));
- EXPECT_TRUE(add_field(request, client));
+ EXPECT_TRUE(add_auth_field(request, client));
- const auto response2 = server.get_response(request);
+ auto response2 = server.get_response(request);
ASSERT_TRUE(bool(response2));
EXPECT_TRUE(is_unauthorized(*response2));
+ EXPECT_TRUE(response2->m_header_info.m_etc_fields.empty());
+ response2->m_header_info.m_etc_fields = response2->m_additional_fields;
const auth_responses parsed1 = parse_response(*response);
const auth_responses parsed2 = parse_response(*response2);
@@ -564,7 +568,7 @@ TEST(HTTP_Auth, DogFood)
// with stale=true client should reset
request.m_header_info.m_etc_fields.clear();
EXPECT_EQ(http::http_client_auth::kSuccess, client.handle_401(*response2));
- EXPECT_TRUE(add_field(request, client));
+ EXPECT_TRUE(add_auth_field(request, client));
EXPECT_FALSE(bool(server.get_response(request)));
// client should give up if stale=false
@@ -654,7 +658,7 @@ TEST(HTTP_Client_Auth, MD5)
EXPECT_EQ(http::http_client_auth::kBadPassword, auth.handle_401(response));
- response.m_additional_fields.front().second.append(u8"," + write_fields({{u8"stale", u8"TRUE"}}));
+ response.m_header_info.m_etc_fields.front().second.append(u8"," + write_fields({{u8"stale", u8"TRUE"}}));
EXPECT_EQ(http::http_client_auth::kSuccess, auth.handle_401(response));
}
@@ -718,7 +722,17 @@ TEST(HTTP_Client_Auth, MD5_auth)
}
EXPECT_EQ(http::http_client_auth::kBadPassword, auth.handle_401(response));
- response.m_additional_fields.back().second.append(u8"," + write_fields({{u8"stale", u8"trUe"}}));
+ response.m_header_info.m_etc_fields.back().second.append(u8"," + write_fields({{u8"stale", u8"trUe"}}));
EXPECT_EQ(http::http_client_auth::kSuccess, auth.handle_401(response));
}
+
+TEST(HTTP, Add_Field)
+{
+ std::string str{"leading text"};
+ epee::net_utils::http::add_field(str, "foo", "bar");
+ epee::net_utils::http::add_field(str, std::string("bar"), std::string("foo"));
+ epee::net_utils::http::add_field(str, {"moarbars", "moarfoo"});
+
+ EXPECT_STREQ("leading textfoo: bar\r\nbar: foo\r\nmoarbars: moarfoo\r\n", str.c_str());
+}
diff --git a/tests/unit_tests/parse_amount.cpp b/tests/unit_tests/parse_amount.cpp
index 6c61d63f1..23e7eb292 100644
--- a/tests/unit_tests/parse_amount.cpp
+++ b/tests/unit_tests/parse_amount.cpp
@@ -30,7 +30,7 @@
#include "gtest/gtest.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_basic/cryptonote_format_utils.h"
using namespace cryptonote;
diff --git a/tests/unit_tests/serialization.cpp b/tests/unit_tests/serialization.cpp
index 1083dd4cc..5b8486a19 100644
--- a/tests/unit_tests/serialization.cpp
+++ b/tests/unit_tests/serialization.cpp
@@ -35,8 +35,8 @@
#include <vector>
#include <boost/foreach.hpp>
#include <boost/archive/portable_binary_iarchive.hpp>
-#include "cryptonote_core/cryptonote_basic.h"
-#include "cryptonote_core/cryptonote_basic_impl.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
#include "ringct/rctSigs.h"
#include "serialization/serialization.h"
#include "serialization/binary_archive.h"
diff --git a/tests/unit_tests/test_format_utils.cpp b/tests/unit_tests/test_tx_utils.cpp
index 463d62529..91d5d5d67 100644
--- a/tests/unit_tests/test_format_utils.cpp
+++ b/tests/unit_tests/test_tx_utils.cpp
@@ -33,7 +33,7 @@
#include <vector>
#include "common/util.h"
-#include "cryptonote_core/cryptonote_format_utils.h"
+#include "cryptonote_core/cryptonote_tx_utils.h"
namespace
{
diff --git a/tests/unit_tests/varint.cpp b/tests/unit_tests/varint.cpp
index a483cbd5f..a87eeb14b 100644
--- a/tests/unit_tests/varint.cpp
+++ b/tests/unit_tests/varint.cpp
@@ -34,8 +34,8 @@
#include <iostream>
#include <vector>
#include <boost/foreach.hpp>
-#include "cryptonote_core/cryptonote_basic.h"
-#include "cryptonote_core/cryptonote_basic_impl.h"
+#include "cryptonote_basic/cryptonote_basic.h"
+#include "cryptonote_basic/cryptonote_basic_impl.h"
#include "serialization/serialization.h"
#include "serialization/binary_archive.h"
#include "serialization/json_archive.h"