diff options
37 files changed, 318 insertions, 186 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 3eddfca0e..2964e299c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -658,6 +658,11 @@ if(NOT Boost_FOUND) die("Could not find Boost libraries, please make sure you have installed Boost or libboost-all-dev (1.58) or the equivalent") elseif(Boost_FOUND) message(STATUS "Found Boost Version: ${Boost_VERSION}") + if (Boost_VERSION VERSION_LESS 1.62 AND NOT (OPENSSL_VERSION VERSION_LESS 1.1)) + message(FATAL_ERROR "Boost older than 1.62 is too old to link with OpenSSL 1.1 or newer. " + "Update Boost or install OpenSSL 1.0 and set path to it when running cmake: " + "cmake -DOPENSSL_ROOT_DIR='/usr/include/openssl-1.0;/usr/lib/openssl-1.0'") + endif() endif() include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) @@ -702,6 +707,8 @@ include(version.cmake) find_path(ZMQ_INCLUDE_PATH zmq.hpp) find_library(ZMQ_LIB zmq) +find_library(PGM_LIBRARY pgm) +find_library(NORM_LIBRARY norm) find_library(SODIUM_LIBRARY sodium) if(NOT ZMQ_INCLUDE_PATH) @@ -710,6 +717,12 @@ endif() if(NOT ZMQ_LIB) message(FATAL_ERROR "Could not find required libzmq") endif() +if(PGM_LIBRARY) + set(ZMQ_LIB "${ZMQ_LIB};${PGM_LIBRARY}") +endif() +if(NORM_LIBRARY) + set(ZMQ_LIB "${ZMQ_LIB};${NORM_LIBRARY}") +endif() if(SODIUM_LIBRARY) set(ZMQ_LIB "${ZMQ_LIB};${SODIUM_LIBRARY}") endif() @@ -1,7 +1,7 @@ # Monero -Copyright (c) 2014-2017, The Monero Project -Portions Copyright (c) 2012-2013, The Cryptonote developers +Copyright (c) 2014-2017 The Monero Project. +Portions Copyright (c) 2012-2013 The Cryptonote developers. ## Development Resources diff --git a/contrib/epee/include/net/http_base.h b/contrib/epee/include/net/http_base.h index 144acad9d..a66fb7c23 100644..100755 --- a/contrib/epee/include/net/http_base.h +++ b/contrib/epee/include/net/http_base.h @@ -46,6 +46,7 @@ namespace net_utils { enum http_method{ + http_method_options, http_method_get, http_method_post, http_method_put, @@ -115,6 +116,7 @@ namespace net_utils std::string m_host; //"Host:" std::string m_cookie; //"Cookie:" std::string m_user_agent; //"User-Agent:" + std::string m_origin; //"Origin:" fields_list m_etc_fields; void clear() @@ -128,6 +130,7 @@ namespace net_utils m_host.clear(); m_cookie.clear(); m_user_agent.clear(); + m_origin.clear(); m_etc_fields.clear(); } }; diff --git a/contrib/epee/include/net/http_client.h b/contrib/epee/include/net/http_client.h index ed89ca0c7..80a4504e3 100644..100755 --- a/contrib/epee/include/net/http_client.h +++ b/contrib/epee/include/net/http_client.h @@ -749,10 +749,10 @@ using namespace std; MTRACE("http_stream_filter::parse_cached_header(*)"); STATIC_REGEXP_EXPR_1(rexp_mach_field, - "\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)|(User-Agent)" - // 12 3 4 5 6 7 8 9 10 + "\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)|(User-Agent)|(Origin)" + // 12 3 4 5 6 7 8 9 10 11 "|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]", - //11 1213 14 + //12 13 14 15 boost::regex::icase | boost::regex::normal); boost::smatch result; @@ -764,7 +764,7 @@ using namespace std; //lookup all fields and fill well-known fields while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched) { - const size_t field_val = 13; + const size_t field_val = 14; //const size_t field_etc_name = 11; int i = 2; //start position = 2 @@ -788,8 +788,10 @@ using namespace std; body_info.m_cookie = result[field_val]; else if(result[i++].matched)//"User-Agent" body_info.m_user_agent = result[field_val]; + else if(result[i++].matched)//"Origin" + body_info.m_origin = 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]); + body_info.m_etc_fields.emplace_back(result[12], 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 babe49ad7..652d8ff6f 100644..100755 --- a/contrib/epee/include/net/http_protocol_handler.h +++ b/contrib/epee/include/net/http_protocol_handler.h @@ -54,6 +54,7 @@ namespace net_utils struct http_server_config { std::string m_folder; + std::vector<std::string> m_access_control_origins; boost::optional<login> m_user; critical_section m_lock; }; @@ -193,6 +194,7 @@ namespace net_utils response.m_response_code = 200; response.m_response_comment = "OK"; response.m_body.clear(); + return m_config.m_phandler->handle_http_request(query_info, response, m_conn_context); } diff --git a/contrib/epee/include/net/http_protocol_handler.inl b/contrib/epee/include/net/http_protocol_handler.inl index c92a13bcc..c3350bf73 100644..100755 --- a/contrib/epee/include/net/http_protocol_handler.inl +++ b/contrib/epee/include/net/http_protocol_handler.inl @@ -316,7 +316,10 @@ namespace net_utils CHECK_AND_ASSERT_MES(result[0].matched, false, "simple_http_connection_handler::analize_http_method() assert failed..."); http_ver_major = boost::lexical_cast<int>(result[11]); http_ver_minor = boost::lexical_cast<int>(result[12]); - if(result[4].matched) + + if(result[3].matched) + method = http::http_method_options; + else if(result[4].matched) method = http::http_method_get; else if(result[5].matched) method = http::http_method_head; @@ -472,8 +475,8 @@ namespace net_utils bool simple_http_connection_handler<t_connection_context>::parse_cached_header(http_header_info& body_info, const std::string& m_cache_to_process, size_t pos) { STATIC_REGEXP_EXPR_1(rexp_mach_field, - "\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)|(User-Agent)" - // 12 3 4 5 6 7 8 9 10 + "\n?((Connection)|(Referer)|(Content-Length)|(Content-Type)|(Transfer-Encoding)|(Content-Encoding)|(Host)|(Cookie)|(User-Agent)|(Origin)" + // 12 3 4 5 6 7 8 9 10 11 "|([\\w-]+?)) ?: ?((.*?)(\r?\n))[^\t ]", //11 1213 14 boost::regex::icase | boost::regex::normal); @@ -487,8 +490,8 @@ namespace net_utils //lookup all fields and fill well-known fields while( boost::regex_search( it_current_bound, it_end_bound, result, rexp_mach_field, boost::match_default) && result[0].matched) { - const size_t field_val = 13; - const size_t field_etc_name = 11; + const size_t field_val = 14; + const size_t field_etc_name = 12; int i = 2; //start position = 2 if(result[i++].matched)//"Connection" @@ -509,6 +512,8 @@ namespace net_utils body_info.m_cookie = result[field_val]; else if(result[i++].matched)//"User-Agent" body_info.m_user_agent = result[field_val]; + else if(result[i++].matched)//"Origin" + body_info.m_origin = result[field_val]; else if(result[i++].matched)//e.t.c (HAVE TO BE MATCHED!) body_info.m_etc_fields.push_back(std::pair<std::string, std::string>(result[field_etc_name], result[field_val])); else @@ -537,17 +542,27 @@ namespace net_utils template<class t_connection_context> bool simple_http_connection_handler<t_connection_context>::handle_request_and_send_response(const http::http_request_info& query_info) { - http_response_info response; - bool res = handle_request(query_info, response); + http_response_info response{}; //CHECK_AND_ASSERT_MES(res, res, "handle_request(query_info, response) returned false" ); + bool res = true; + + if (query_info.m_http_method != http::http_method_options) + { + res = handle_request(query_info, response); + } + else + { + response.m_response_code = 200; + response.m_response_comment = "OK"; + } std::string response_data = get_response_header(response); - //LOG_PRINT_L0("HTTP_SEND: << \r\n" << response_data + response.m_body); + LOG_PRINT_L3("HTTP_RESPONSE_HEAD: << \r\n" << response_data); m_psnd_hndlr->do_send((void*)response_data.data(), response_data.size()); - if(response.m_body.size() && (query_info.m_http_method != http::http_method_head)) + if ((response.m_body.size() && (query_info.m_http_method != http::http_method_head)) || (query_info.m_http_method == http::http_method_options)) m_psnd_hndlr->do_send((void*)response.m_body.data(), response.m_body.size()); return res; } @@ -579,7 +594,6 @@ namespace net_utils response.m_response_comment = "OK"; response.m_mime_tipe = get_file_mime_tipe(uri_to_path); - return true; } //----------------------------------------------------------------------------------- @@ -591,8 +605,12 @@ namespace net_utils "Server: Epee-based\r\n" "Content-Length: "; buf += boost::lexical_cast<std::string>(response.m_body.size()) + "\r\n"; - buf += "Content-Type: "; - buf += response.m_mime_tipe + "\r\n"; + + if(!response.m_mime_tipe.empty()) + { + buf += "Content-Type: "; + buf += response.m_mime_tipe + "\r\n"; + } buf += "Last-Modified: "; time_t tm; @@ -612,6 +630,19 @@ namespace net_utils m_want_close = true; } } + + // Cross-origin resource sharing + if(m_query_info.m_header_info.m_origin.size()) + { + if (std::binary_search(m_config.m_access_control_origins.begin(), m_config.m_access_control_origins.end(), m_query_info.m_header_info.m_origin)) + { + buf += "Access-Control-Allow-Origin: "; + buf += m_query_info.m_header_info.m_origin; + buf += "\r\n"; + buf += "Access-Control-Allow-Methods: POST, PUT, GET, OPTIONS\r\n"; + } + } + //add additional fields, if it is for(fields_list::const_iterator it = response.m_additional_fields.begin(); it!=response.m_additional_fields.end(); it++) buf += it->first + ":" + it->second + "\r\n"; diff --git a/contrib/epee/include/net/http_server_handlers_map2.h b/contrib/epee/include/net/http_server_handlers_map2.h index 429e3e1af..429e3e1af 100644..100755 --- a/contrib/epee/include/net/http_server_handlers_map2.h +++ b/contrib/epee/include/net/http_server_handlers_map2.h diff --git a/contrib/epee/include/net/http_server_impl_base.h b/contrib/epee/include/net/http_server_impl_base.h index acecbb2d4..0788c6a4b 100644..100755 --- a/contrib/epee/include/net/http_server_impl_base.h +++ b/contrib/epee/include/net/http_server_impl_base.h @@ -56,6 +56,7 @@ namespace epee {} bool init(const std::string& bind_port = "0", const std::string& bind_ip = "0.0.0.0", + std::vector<std::string> access_control_origins = std::vector<std::string>(), boost::optional<net_utils::http::login> user = boost::none) { @@ -65,6 +66,10 @@ namespace epee //here set folder for hosting reqests m_net_server.get_config_object().m_folder = ""; + //set access control allow origins if configured + std::sort(access_control_origins.begin(), access_control_origins.end()); + m_net_server.get_config_object().m_access_control_origins = std::move(access_control_origins); + m_net_server.get_config_object().m_user = std::move(user); MGINFO("Binding on " << bind_ip << ":" << bind_port); diff --git a/contrib/epee/include/net/net_helper.h b/contrib/epee/include/net/net_helper.h index c8e4c7818..ee0e13fc1 100644 --- a/contrib/epee/include/net/net_helper.h +++ b/contrib/epee/include/net/net_helper.h @@ -36,6 +36,7 @@ #include <istream> #include <ostream> #include <string> +#include <boost/version.hpp> #include <boost/asio.hpp> #include <boost/asio/ssl.hpp> #include <boost/asio/steady_timer.hpp> @@ -382,7 +383,7 @@ namespace net_utils char local_buff[10000] = {0}; - async_read(local_buff, boost::asio::transfer_at_least(1), hndlr); + async_read(local_buff, sizeof(local_buff), boost::asio::transfer_at_least(1), hndlr); // Block until the asynchronous operation has completed. while (ec == boost::asio::error::would_block && !boost::interprocess::ipcdetail::atomic_read32(&m_shutdowned)) @@ -463,7 +464,7 @@ namespace net_utils handler_obj hndlr(ec, bytes_transfered); - async_read((char*)buff.data(), boost::asio::transfer_at_least(buff.size()), hndlr); + async_read((char*)buff.data(), buff.size(), boost::asio::transfer_at_least(buff.size()), hndlr); // Block until the asynchronous operation has completed. while (ec == boost::asio::error::would_block && !boost::interprocess::ipcdetail::atomic_read32(&m_shutdowned)) @@ -576,7 +577,14 @@ namespace net_utils m_io_service.run_one(); } // Ignore "short read" error - if (ec.category() == boost::asio::error::get_ssl_category() && ec.value() != ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ)) + if (ec.category() == boost::asio::error::get_ssl_category() && + ec.value() != +#if BOOST_VERSION >= 106200 + boost::asio::ssl::error::stream_truncated +#else // older Boost supports only OpenSSL 1.0, so 1.0-only macros are appropriate + ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ) +#endif + ) MDEBUG("Problems at ssl shutdown: " << ec.message()); } @@ -599,12 +607,12 @@ namespace net_utils boost::asio::async_write(m_ssl_socket.next_layer(), boost::asio::buffer(data, sz), boost::lambda::var(ec) = boost::lambda::_1); } - void async_read(char* buff, boost::asio::detail::transfer_at_least_t transfer_at_least, handler_obj& hndlr) + void async_read(char* buff, size_t sz, boost::asio::detail::transfer_at_least_t transfer_at_least, handler_obj& hndlr) { if(!m_ssl) - boost::asio::async_read(m_ssl_socket.next_layer(), boost::asio::buffer(buff, sizeof(buff)), transfer_at_least, hndlr); + boost::asio::async_read(m_ssl_socket.next_layer(), boost::asio::buffer(buff, sz), transfer_at_least, hndlr); else - boost::asio::async_read(m_ssl_socket, boost::asio::buffer(buff, sizeof(buff)), transfer_at_least, hndlr); + boost::asio::async_read(m_ssl_socket, boost::asio::buffer(buff, sz), transfer_at_least, hndlr); } diff --git a/contrib/epee/src/CMakeLists.txt b/contrib/epee/src/CMakeLists.txt index af3c6ca5f..3b41f415e 100644 --- a/contrib/epee/src/CMakeLists.txt +++ b/contrib/epee/src/CMakeLists.txt @@ -49,6 +49,5 @@ target_link_libraries(epee easylogging ${Boost_FILESYSTEM_LIBRARY} PRIVATE - ssl - crypto + ${OPENSSL_LIBRARIES} ${EXTRA_LIBRARIES}) diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 3979a5edf..5bd02bcf7 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1123,6 +1123,12 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags) m_folder = filename; +#ifdef __OpenBSD__ + if ((mdb_flags & MDB_WRITEMAP) == 0) { + MCLOG_RED(el::Level::Info, "global", "Running on OpenBSD: forcing WRITEMAP"); + mdb_flags |= MDB_WRITEMAP; + } +#endif // set up lmdb environment if ((result = mdb_env_create(&m_env))) throw0(DB_ERROR(lmdb_error("Failed to create lmdb environment: ", result).c_str())); diff --git a/src/blockchain_utilities/CMakeLists.txt b/src/blockchain_utilities/CMakeLists.txt index 0eaf71084..bd32e0c55 100644 --- a/src/blockchain_utilities/CMakeLists.txt +++ b/src/blockchain_utilities/CMakeLists.txt @@ -93,6 +93,7 @@ endif() set_property(TARGET blockchain_import PROPERTY OUTPUT_NAME "monero-blockchain-import") +install(TARGETS blockchain_import DESTINATION bin) monero_add_executable(blockchain_export ${blockchain_export_sources} @@ -114,4 +115,5 @@ target_link_libraries(blockchain_export set_property(TARGET blockchain_export PROPERTY OUTPUT_NAME "monero-blockchain-export") +install(TARGETS blockchain_export DESTINATION bin) diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h index 5a61fc78c..e38e15cb2 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h @@ -150,7 +150,7 @@ namespace config uint64_t const CRYPTONOTE_PUBLIC_ADDRESS_BASE58_PREFIX = 18; uint64_t const CRYPTONOTE_PUBLIC_INTEGRATED_ADDRESS_BASE58_PREFIX = 19; - uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 26; + uint64_t const CRYPTONOTE_PUBLIC_SUBADDRESS_BASE58_PREFIX = 42; uint16_t const P2P_DEFAULT_PORT = 18080; uint16_t const RPC_DEFAULT_PORT = 18081; uint16_t const ZMQ_RPC_DEFAULT_PORT = 18082; diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 933914363..9d89c6280 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -139,14 +139,20 @@ Blockchain::Blockchain(tx_memory_pool& tx_pool) : bool Blockchain::have_tx(const crypto::hash &id) const { LOG_PRINT_L3("Blockchain::" << __func__); - CRITICAL_REGION_LOCAL(m_blockchain_lock); + // WARNING: this function does not take m_blockchain_lock, and thus should only call read only + // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as + // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must + // lock if it is otherwise needed. return m_db->tx_exists(id); } //------------------------------------------------------------------ bool Blockchain::have_tx_keyimg_as_spent(const crypto::key_image &key_im) const { LOG_PRINT_L3("Blockchain::" << __func__); - CRITICAL_REGION_LOCAL(m_blockchain_lock); + // WARNING: this function does not take m_blockchain_lock, and thus should only call read only + // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as + // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must + // lock if it is otherwise needed. return m_db->has_key_image(key_im); } //------------------------------------------------------------------ @@ -287,7 +293,10 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke uint64_t Blockchain::get_current_blockchain_height() const { LOG_PRINT_L3("Blockchain::" << __func__); - CRITICAL_REGION_LOCAL(m_blockchain_lock); + // WARNING: this function does not take m_blockchain_lock, and thus should only call read only + // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as + // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must + // lock if it is otherwise needed. return m_db->height(); } //------------------------------------------------------------------ @@ -571,7 +580,10 @@ crypto::hash Blockchain::get_tail_id(uint64_t& height) const crypto::hash Blockchain::get_tail_id() const { LOG_PRINT_L3("Blockchain::" << __func__); - CRITICAL_REGION_LOCAL(m_blockchain_lock); + // WARNING: this function does not take m_blockchain_lock, and thus should only call read only + // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as + // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must + // lock if it is otherwise needed. return m_db->top_block_hash(); } //------------------------------------------------------------------ @@ -633,7 +645,10 @@ bool Blockchain::get_short_chain_history(std::list<crypto::hash>& ids) const crypto::hash Blockchain::get_block_id_by_height(uint64_t height) const { LOG_PRINT_L3("Blockchain::" << __func__); - CRITICAL_REGION_LOCAL(m_blockchain_lock); + // WARNING: this function does not take m_blockchain_lock, and thus should only call read only + // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as + // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must + // lock if it is otherwise needed. try { return m_db->get_block_hash_from_height(height); @@ -1928,7 +1943,10 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc uint64_t Blockchain::block_difficulty(uint64_t i) const { LOG_PRINT_L3("Blockchain::" << __func__); - CRITICAL_REGION_LOCAL(m_blockchain_lock); + // WARNING: this function does not take m_blockchain_lock, and thus should only call read only + // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as + // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must + // lock if it is otherwise needed. try { return m_db->get_block_difficulty(i); @@ -2209,7 +2227,10 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, block_verification_ size_t Blockchain::get_total_transactions() const { LOG_PRINT_L3("Blockchain::" << __func__); - CRITICAL_REGION_LOCAL(m_blockchain_lock); + // WARNING: this function does not take m_blockchain_lock, and thus should only call read only + // m_db functions which do not depend on one another (ie, no getheight + gethash(height-1), as + // well as not accessing class members, even read only (ie, m_invalid_blocks). The caller must + // lock if it is otherwise needed. return m_db->get_tx_count(); } //------------------------------------------------------------------ diff --git a/src/cryptonote_core/cryptonote_tx_utils.cpp b/src/cryptonote_core/cryptonote_tx_utils.cpp index 586df9079..96f6ee872 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.cpp +++ b/src/cryptonote_core/cryptonote_tx_utils.cpp @@ -158,7 +158,7 @@ namespace cryptonote return destinations[0].addr.m_view_public_key; } //--------------------------------------------------------------- - bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const cryptonote::account_public_address& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct) + bool construct_tx_and_get_tx_key(const account_keys& sender_account_keys, const std::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct) { if (destinations.empty()) { @@ -301,7 +301,7 @@ namespace cryptonote account_public_address single_dest_subaddress; for(const tx_destination_entry& dst_entr: destinations) { - if (dst_entr.addr == change_addr) + if (change_addr && dst_entr.addr == *change_addr) continue; if (unique_dst_addresses.count(dst_entr.addr) == 0) { @@ -354,7 +354,7 @@ namespace cryptonote } bool r; - if (dst_entr.addr == change_addr) + if (change_addr && dst_entr.addr == *change_addr) { // sending change to yourself; derivation = a*R r = crypto::generate_key_derivation(txkey.pub, sender_account_keys.m_view_secret_key, derivation); @@ -565,13 +565,13 @@ namespace cryptonote return true; } //--------------------------------------------------------------- - bool construct_tx(const account_keys& sender_account_keys, 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(const account_keys& sender_account_keys, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time) { std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses; subaddresses[sender_account_keys.m_account_address.m_spend_public_key] = {0,0}; crypto::secret_key tx_key; std::vector<crypto::secret_key> additional_tx_keys; - return construct_tx_and_get_tx_key(sender_account_keys, subaddresses, sources, destinations, destinations.back().addr, extra, tx, unlock_time, tx_key, additional_tx_keys); + return construct_tx_and_get_tx_key(sender_account_keys, subaddresses, sources, destinations, change_addr, extra, tx, unlock_time, tx_key, additional_tx_keys); } //--------------------------------------------------------------- bool generate_genesis_block( diff --git a/src/cryptonote_core/cryptonote_tx_utils.h b/src/cryptonote_core/cryptonote_tx_utils.h index b5de44b88..9a3b2484d 100644 --- a/src/cryptonote_core/cryptonote_tx_utils.h +++ b/src/cryptonote_core/cryptonote_tx_utils.h @@ -73,8 +73,8 @@ namespace cryptonote //--------------------------------------------------------------- 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, 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::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const cryptonote::account_public_address& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false); + bool construct_tx(const account_keys& sender_account_keys, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, 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::unordered_map<crypto::public_key, subaddress_index>& subaddresses, std::vector<tx_source_entry>& sources, const std::vector<tx_destination_entry>& destinations, const boost::optional<cryptonote::account_public_address>& change_addr, std::vector<uint8_t> extra, transaction& tx, uint64_t unlock_time, crypto::secret_key &tx_key, std::vector<crypto::secret_key> &additional_tx_keys, bool rct = false); bool generate_genesis_block( block& bl diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp index 9095aacae..b3ce30d0c 100644..100755 --- a/src/rpc/core_rpc_server.cpp +++ b/src/rpc/core_rpc_server.cpp @@ -101,7 +101,7 @@ namespace cryptonote 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) + std::move(port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login) ); } //------------------------------------------------------------------------------------------------------------------------------ diff --git a/src/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp index 4435f74d1..93309bf3c 100644..100755 --- a/src/rpc/rpc_args.cpp +++ b/src/rpc/rpc_args.cpp @@ -28,6 +28,7 @@ // #include "rpc_args.h" +#include <boost/algorithm/string.hpp> #include <boost/asio/ip/address.hpp> #include "common/command_line.h" #include "common/i18n.h" @@ -38,6 +39,7 @@ namespace cryptonote : 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 rpc-bind-ip value is NOT a loopback (local) IP")}) + , rpc_access_control_origins({"rpc-access-control-origins", rpc_args::tr("Specify a comma separated list of origins to allow cross origin resource sharing"), ""}) {} const char* rpc_args::tr(const char* str) { return i18n_translate(str, "cryptonote::rpc_args"); } @@ -48,6 +50,7 @@ namespace cryptonote 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); + command_line::add_arg(desc, arg.rpc_access_control_origins); } boost::optional<rpc_args> rpc_args::process(const boost::program_options::variables_map& vm) @@ -91,6 +94,21 @@ namespace cryptonote } } + auto access_control_origins_input = command_line::get_arg(vm, arg.rpc_access_control_origins); + if (!access_control_origins_input.empty()) + { + if (!config.login) + { + LOG_ERROR(arg.rpc_access_control_origins.name << tr(" requires RFC server password --") << arg.rpc_login.name << tr(" cannot be empty")); + return boost::none; + } + + std::vector<std::string> access_control_origins; + boost::split(access_control_origins, access_control_origins_input, boost::is_any_of(",")); + std::for_each(access_control_origins.begin(), access_control_origins.end(), boost::bind(&boost::trim<std::string>, _1, std::locale::classic())); + config.access_control_origins = std::move(access_control_origins); + } + return {std::move(config)}; } } diff --git a/src/rpc/rpc_args.h b/src/rpc/rpc_args.h index d6e7bab07..72b5aa706 100644..100755 --- a/src/rpc/rpc_args.h +++ b/src/rpc/rpc_args.h @@ -53,6 +53,7 @@ namespace cryptonote 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; + const command_line::arg_descriptor<std::string> rpc_access_control_origins; }; static const char* tr(const char* str); @@ -62,6 +63,7 @@ namespace cryptonote static boost::optional<rpc_args> process(const boost::program_options::variables_map& vm); std::string bind_ip; + std::vector<std::string> access_control_origins; boost::optional<tools::login> login; // currently `boost::none` if unspecified by user }; } diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index db7e60cd7..8f7befc8c 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -1044,8 +1044,7 @@ void WalletImpl::setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex // - confirmed_transfer_details) PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const string &payment_id, optional<uint64_t> amount, uint32_t mixin_count, - uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, - PendingTransaction::Priority priority) + PendingTransaction::Priority priority, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices) { clearStatus(); diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index ecb218ea0..051eda3ba 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -73,7 +73,7 @@ public: int status() const; std::string errorString() const; bool setPassword(const std::string &password); - std::string address(uint32_t accountIndex, uint32_t addressIndex) const; + std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const; std::string integratedAddress(const std::string &payment_id) const; std::string secretViewKey() const; std::string publicViewKey() const; @@ -88,8 +88,8 @@ public: ConnectionStatus connected() const; void setTrustedDaemon(bool arg); bool trustedDaemon() const; - uint64_t balance(uint32_t accountIndex) const; - uint64_t unlockedBalance(uint32_t accountIndex) const; + uint64_t balance(uint32_t accountIndex = 0) const; + uint64_t unlockedBalance(uint32_t accountIndex = 0) const; uint64_t blockChainHeight() const; uint64_t approximateBlockChainHeight() const; uint64_t daemonBlockChainHeight() const; @@ -117,9 +117,9 @@ public: PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id, optional<uint64_t> amount, uint32_t mixin_count, - uint32_t subaddr_account, - std::set<uint32_t> subaddr_indices, - PendingTransaction::Priority priority = PendingTransaction::Priority_Low); + PendingTransaction::Priority priority = PendingTransaction::Priority_Low, + uint32_t subaddr_account = 0, + std::set<uint32_t> subaddr_indices = {}); virtual PendingTransaction * createSweepUnmixableTransaction(); bool submitTransaction(const std::string &fileName); virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename); diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index cc0e9e7e2..22afac7b7 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -692,20 +692,20 @@ void wallet2::expand_subaddresses(const cryptonote::subaddress_index& index) //---------------------------------------------------------------------------------------------------- std::string wallet2::get_subaddress_label(const cryptonote::subaddress_index& index) const { - if (index.major >= m_subaddress_labels.size()) - throw std::runtime_error("index.major is out of bound"); - if (index.minor >= m_subaddress_labels[index.major].size()) - throw std::runtime_error("index.minor is out of bound"); + if (index.major >= m_subaddress_labels.size() || index.minor >= m_subaddress_labels[index.major].size()) + { + MERROR("Subaddress label doesn't exist"); + return ""; + } return m_subaddress_labels[index.major][index.minor]; } //---------------------------------------------------------------------------------------------------- void wallet2::set_subaddress_label(const cryptonote::subaddress_index& index, const std::string &label) { - if (index.major >= m_subaddress_labels.size()) - throw std::runtime_error("index.major is out of bound"); - if (index.minor >= m_subaddress_labels[index.major].size()) - throw std::runtime_error("index.minor is out of bound"); - m_subaddress_labels[index.major][index.minor] = label; + if (index.major >= m_subaddress_labels.size() || index.minor >= m_subaddress_labels[index.major].size()) + MERROR("Subaddress index is out of bounds. Failed to set subaddress label."); + else + m_subaddress_labels[index.major][index.minor] = label; } //---------------------------------------------------------------------------------------------------- /*! @@ -788,7 +788,7 @@ void wallet2::scan_output(const cryptonote::account_keys &keys, const cryptonote { tx_scan_info.money_transfered = tools::decodeRct(tx.rct_signatures, tx_scan_info.received->derivation, i, tx_scan_info.mask); } - tx_money_got_in_outs[tx_scan_info.received->index] = tx_scan_info.money_transfered; + tx_money_got_in_outs[tx_scan_info.received->index] += tx_scan_info.money_transfered; tx_scan_info.amount = tx_scan_info.money_transfered; ++num_vouts_received; } @@ -1520,7 +1520,7 @@ void wallet2::pull_next_blocks(uint64_t start_height, uint64_t &blocks_start_hei void wallet2::remove_obsolete_pool_txs(const std::vector<crypto::hash> &tx_hashes) { // remove pool txes to us that aren't in the pool anymore - std::unordered_map<crypto::hash, wallet2::payment_details>::iterator uit = m_unconfirmed_payments.begin(); + std::unordered_multimap<crypto::hash, wallet2::payment_details>::iterator uit = m_unconfirmed_payments.begin(); while (uit != m_unconfirmed_payments.end()) { const crypto::hash &txid = uit->second.m_tx_hash; @@ -4751,7 +4751,7 @@ static size_t estimate_rct_tx_size(int n_inputs, int mixin, int n_outputs) size += (2*64*32+32+64*32) * n_outputs; // MGs - size += n_inputs * (32 * (mixin+1) + 32); + size += n_inputs * (64 * (mixin+1) + 32); // mixRing - not serialized, can be reconstructed /* size += 2 * 32 * (mixin+1) * n_inputs; */ diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 26680c3da..746255fa9 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -467,8 +467,8 @@ namespace tools size_t get_num_subaddresses(uint32_t index_major) const { return index_major < m_subaddress_labels.size() ? m_subaddress_labels[index_major].size() : 0; } void add_subaddress(uint32_t index_major, const std::string& label); // throws when index is out of bound void expand_subaddresses(const cryptonote::subaddress_index& index); - std::string get_subaddress_label(const cryptonote::subaddress_index& index) const; // throws when index is out of bound - void set_subaddress_label(const cryptonote::subaddress_index &index, const std::string &label); // throws when index is out of bound + std::string get_subaddress_label(const cryptonote::subaddress_index& index) const; + void set_subaddress_label(const cryptonote::subaddress_index &index, const std::string &label); /*! * \brief Tells if the wallet file is deprecated. */ @@ -1042,7 +1042,10 @@ namespace boost x.m_amount_out += x.m_change; } if (ver < 7) + { + x.m_subaddr_account = 0; return; + } a & x.m_subaddr_account; a & x.m_subaddr_indices; } @@ -1083,7 +1086,10 @@ namespace boost } a & x.m_unlock_time; if (ver < 5) + { + x.m_subaddr_account = 0; return; + } a & x.m_subaddr_account; a & x.m_subaddr_indices; } @@ -1099,7 +1105,10 @@ namespace boost return; a & x.m_timestamp; if (ver < 2) + { + x.m_subaddr_index = {}; return; + } a & x.m_subaddr_index; } @@ -1110,7 +1119,10 @@ namespace boost a & x.m_payment_id; a & x.m_description; if (ver < 17) + { + x.m_is_subaddress = false; return; + } a & x.m_is_subaddress; } @@ -1140,7 +1152,10 @@ namespace boost a & x.use_rct; a & x.dests; if (ver < 1) + { + x.subaddr_account = 0; return; + } a & x.subaddr_account; a & x.subaddr_indices; } diff --git a/src/wallet/wallet2_api.h b/src/wallet/wallet2_api.h index 4d734ab94..a8c150ca7 100644 --- a/src/wallet/wallet2_api.h +++ b/src/wallet/wallet2_api.h @@ -360,7 +360,7 @@ struct Wallet //! in case error status, returns error string virtual std::string errorString() const = 0; virtual bool setPassword(const std::string &password) = 0; - virtual std::string address(uint32_t accountIndex, uint32_t addressIndex) const = 0; + virtual std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const = 0; std::string mainAddress() const { return address(0, 0); } virtual std::string path() const = 0; virtual bool testnet() const = 0; @@ -476,14 +476,14 @@ struct Wallet virtual ConnectionStatus connected() const = 0; virtual void setTrustedDaemon(bool arg) = 0; virtual bool trustedDaemon() const = 0; - virtual uint64_t balance(uint32_t accountIndex) const = 0; + virtual uint64_t balance(uint32_t accountIndex = 0) const = 0; uint64_t balanceAll() const { uint64_t result = 0; for (uint32_t i = 0; i < numSubaddressAccounts(); ++i) result += balance(i); return result; } - virtual uint64_t unlockedBalance(uint32_t accountIndex) const = 0; + virtual uint64_t unlockedBalance(uint32_t accountIndex = 0) const = 0; uint64_t unlockedBalanceAll() const { uint64_t result = 0; for (uint32_t i = 0; i < numSubaddressAccounts(); ++i) @@ -623,9 +623,9 @@ struct Wallet virtual PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id, optional<uint64_t> amount, uint32_t mixin_count, - uint32_t subaddr_account, - std::set<uint32_t> subaddr_indices, - PendingTransaction::Priority = PendingTransaction::Priority_Low) = 0; + PendingTransaction::Priority = PendingTransaction::Priority_Low, + uint32_t subaddr_account = 0, + std::set<uint32_t> subaddr_indices = {}) = 0; /*! * \brief createSweepUnmixableTransaction creates transaction with unmixable outputs. diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index a048a53ae..acd5357ed 100644..100755 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -216,7 +216,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(rpc_config->bind_ip), std::move(http_login) + std::move(bind_port), std::move(rpc_config->bind_ip), std::move(rpc_config->access_control_origins), std::move(http_login) ); } //------------------------------------------------------------------------------------------------------------------------------ @@ -341,8 +341,7 @@ namespace tools } catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = e.what(); + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); return false; } return true; @@ -369,8 +368,7 @@ namespace tools } catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = e.what(); + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); return false; } return true; @@ -406,8 +404,7 @@ namespace tools } catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = e.what(); + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); return false; } return true; @@ -436,8 +433,7 @@ namespace tools } catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = e.what(); + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); return false; } return true; @@ -454,8 +450,7 @@ namespace tools } catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = e.what(); + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); return false; } return true; @@ -476,8 +471,7 @@ namespace tools } catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = e.what(); + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); return false; } return true; @@ -492,8 +486,7 @@ namespace tools } catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = e.what(); + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); return false; } return true; @@ -618,7 +611,7 @@ namespace tools // reject proposed transactions if there are more than one. see on_transfer_split below. if (ptx_vector.size() != 1) { - er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR; + er.code = WALLET_RPC_ERROR_CODE_TX_TOO_LARGE; er.message = "Transaction would be too large. try /transfer_split."; return false; } @@ -642,22 +635,9 @@ namespace tools } return true; } - catch (const tools::error::daemon_busy& e) - { - er.code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY; - er.message = e.what(); - return false; - } catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR; - er.message = e.what(); - return false; - } - catch (...) - { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR"; + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR); return false; } return true; @@ -725,22 +705,9 @@ namespace tools return true; } - catch (const tools::error::daemon_busy& e) - { - er.code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY; - er.message = e.what(); - return false; - } catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR; - er.message = e.what(); - return false; - } - catch (...) - { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR"; + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR); return false; } return true; @@ -782,22 +749,9 @@ namespace tools return true; } - catch (const tools::error::daemon_busy& e) - { - er.code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY; - er.message = e.what(); - return false; - } catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR; - er.message = e.what(); - return false; - } - catch (...) - { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR"; + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR); return false; } return true; @@ -852,22 +806,9 @@ namespace tools return true; } - catch (const tools::error::daemon_busy& e) - { - er.code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY; - er.message = e.what(); - return false; - } catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR; - er.message = e.what(); - return false; - } - catch (...) - { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR"; + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_GENERIC_TRANSFER_ERROR); return false; } return true; @@ -897,10 +838,9 @@ namespace tools res.payment_id = epee::string_tools::pod_to_hex(payment_id); return true; } - catch (const std::exception &e) + catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = e.what(); + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); return false; } return true; @@ -929,10 +869,9 @@ namespace tools res.payment_id = epee::string_tools::pod_to_hex(info.payment_id); return true; } - catch (const std::exception &e) + catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = e.what(); + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); return false; } return true; @@ -954,8 +893,7 @@ namespace tools } catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = e.what(); + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); return false; } return true; @@ -1185,8 +1123,7 @@ namespace tools } catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = e.what(); + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); return false; } return true; @@ -1258,8 +1195,7 @@ namespace tools } catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = e.what(); + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); return false; } return true; @@ -1494,10 +1430,9 @@ namespace tools } } - catch (...) + catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "Failed"; + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); return false; } @@ -1550,10 +1485,9 @@ namespace tools res.height = height; } - catch (...) + catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "Failed"; + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); return false; } @@ -1730,10 +1664,9 @@ namespace tools m_wallet->rescan_spent(); return true; } - catch (const std::exception &e) + catch (const std::exception& e) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = e.what(); + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); return false; } return true; @@ -1798,7 +1731,7 @@ namespace tools { if (m_wallet_dir.empty()) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.code = WALLET_RPC_ERROR_CODE_NO_WALLET_DIR; er.message = "No wallet dir configured"; return false; } @@ -1866,6 +1799,11 @@ namespace tools } catch (const std::exception& e) { + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); + return false; + } + if (!wal) + { er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; er.message = "Failed to generate wallet"; return false; @@ -1880,7 +1818,7 @@ namespace tools { if (m_wallet_dir.empty()) { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.code = WALLET_RPC_ERROR_CODE_NO_WALLET_DIR; er.message = "No wallet dir configured"; return false; } @@ -1914,13 +1852,13 @@ namespace tools command_line::add_arg(desc, arg_password); po::store(po::parse_command_line(argc, argv, desc), vm2); } - std::unique_ptr<tools::wallet2> wal; + std::unique_ptr<tools::wallet2> wal = nullptr; try { wal = tools::wallet2::make_from_file(vm2, wallet_file).first; } catch (const std::exception& e) { - wal = nullptr; + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); } if (!wal) { @@ -1934,6 +1872,63 @@ namespace tools return true; } //------------------------------------------------------------------------------------------------------------------------------ + void wallet_rpc_server::handle_rpc_exception(const std::exception_ptr& e, epee::json_rpc::error& er, int default_error_code) { + try + { + std::rethrow_exception(e); + } + catch (const tools::error::daemon_busy& e) + { + er.code = WALLET_RPC_ERROR_CODE_DAEMON_IS_BUSY; + er.message = e.what(); + } + catch (const tools::error::zero_destination& e) + { + er.code = WALLET_RPC_ERROR_CODE_ZERO_DESTINATION; + er.message = e.what(); + } + catch (const tools::error::not_enough_money& e) + { + er.code = WALLET_RPC_ERROR_CODE_NOT_ENOUGH_MONEY; + er.message = e.what(); + } + catch (const tools::error::tx_not_possible& e) + { + er.code = WALLET_RPC_ERROR_CODE_TX_NOT_POSSIBLE; + er.message = (boost::format(tr("Transaction not possible. Available only %s, transaction amount %s = %s + %s (fee)")) % + cryptonote::print_money(e.available()) % + cryptonote::print_money(e.tx_amount() + e.fee()) % + cryptonote::print_money(e.tx_amount()) % + cryptonote::print_money(e.fee())).str(); + er.message = e.what(); + } + catch (const tools::error::not_enough_outs_to_mix& e) + { + er.code = WALLET_RPC_ERROR_CODE_NOT_ENOUGH_OUTS_TO_MIX; + er.message = e.what(); + } + catch (const error::file_exists& e) + { + er.code = WALLET_RPC_ERROR_CODE_WALLET_ALREADY_EXISTS; + er.message = "Cannot create wallet. Already exists."; + } + catch (const error::invalid_password& e) + { + er.code = WALLET_RPC_ERROR_CODE_INVALID_PASSWORD; + er.message = "Invalid password."; + } + catch (const std::exception& e) + { + er.code = default_error_code; + er.message = e.what(); + } + catch (...) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR"; + } + } + //------------------------------------------------------------------------------------------------------------------------------ } int main(int argc, char** argv) { diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index 7f4c412e4..f2d98df6f 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -162,6 +162,7 @@ namespace tools void fill_transfer_entry(tools::wallet_rpc::transfer_entry &entry, const crypto::hash &payment_id, const tools::wallet2::payment_details &pd); bool not_open(epee::json_rpc::error& er); uint64_t adjust_mixin(uint64_t mixin); + void handle_rpc_exception(const std::exception_ptr& e, epee::json_rpc::error& er, int default_error_code); wallet2 *m_wallet; std::string m_wallet_dir; diff --git a/src/wallet/wallet_rpc_server_error_codes.h b/src/wallet/wallet_rpc_server_error_codes.h index cc9fd3856..e74e9110b 100644 --- a/src/wallet/wallet_rpc_server_error_codes.h +++ b/src/wallet/wallet_rpc_server_error_codes.h @@ -46,3 +46,11 @@ #define WALLET_RPC_ERROR_CODE_NOT_OPEN -13 #define WALLET_RPC_ERROR_CODE_ACCOUNT_INDEX_OUTOFBOUND -14 #define WALLET_RPC_ERROR_CODE_ADDRESS_INDEX_OUTOFBOUND -15 +#define WALLET_RPC_ERROR_CODE_TX_NOT_POSSIBLE -16 +#define WALLET_RPC_ERROR_CODE_NOT_ENOUGH_MONEY -17 +#define WALLET_RPC_ERROR_CODE_TX_TOO_LARGE -18 +#define WALLET_RPC_ERROR_CODE_NOT_ENOUGH_OUTS_TO_MIX -19 +#define WALLET_RPC_ERROR_CODE_ZERO_DESTINATION -20 +#define WALLET_RPC_ERROR_CODE_WALLET_ALREADY_EXISTS -21 +#define WALLET_RPC_ERROR_CODE_INVALID_PASSWORD -22 +#define WALLET_RPC_ERROR_CODE_NO_WALLET_DIR -23 diff --git a/tests/core_tests/block_validation.cpp b/tests/core_tests/block_validation.cpp index 527059141..db44cd279 100644 --- a/tests/core_tests/block_validation.cpp +++ b/tests/core_tests/block_validation.cpp @@ -350,7 +350,7 @@ bool gen_block_miner_tx_has_2_in::generate(std::vector<test_event_entry>& events destinations.push_back(de); transaction tmp_tx; - if (!construct_tx(miner_account.get_keys(), sources, destinations, std::vector<uint8_t>(), tmp_tx, 0)) + if (!construct_tx(miner_account.get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), tmp_tx, 0)) return false; MAKE_MINER_TX_MANUALLY(miner_tx, blk_0); @@ -393,7 +393,7 @@ bool gen_block_miner_tx_with_txin_to_key::generate(std::vector<test_event_entry> destinations.push_back(de); transaction tmp_tx; - if (!construct_tx(miner_account.get_keys(), sources, destinations, std::vector<uint8_t>(), tmp_tx, 0)) + if (!construct_tx(miner_account.get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), tmp_tx, 0)) return false; MAKE_MINER_TX_MANUALLY(miner_tx, blk_1); diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index f23aa8ecb..2b713cab9 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -563,7 +563,7 @@ bool construct_tx_to_key(const std::vector<test_event_entry>& events, cryptonote vector<tx_destination_entry> destinations; fill_tx_sources_and_destinations(events, blk_head, from, to, amount, fee, nmix, sources, destinations); - return construct_tx(from.get_keys(), sources, destinations, std::vector<uint8_t>(), tx, 0); + return construct_tx(from.get_keys(), sources, destinations, from.get_keys().m_account_address, std::vector<uint8_t>(), tx, 0); } transaction construct_tx_with_fee(std::vector<test_event_entry>& events, const block& blk_head, diff --git a/tests/core_tests/double_spend.inl b/tests/core_tests/double_spend.inl index 438e39e47..bf63503ae 100644 --- a/tests/core_tests/double_spend.inl +++ b/tests/core_tests/double_spend.inl @@ -144,7 +144,7 @@ bool gen_double_spend_in_tx<txs_keeped_by_block>::generate(std::vector<test_even destinations.push_back(de); cryptonote::transaction tx_1; - if (!construct_tx(bob_account.get_keys(), sources, destinations, std::vector<uint8_t>(), tx_1, 0)) + if (!construct_tx(bob_account.get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), tx_1, 0)) return false; SET_EVENT_VISITOR_SETT(events, event_visitor_settings::set_txs_keeped_by_block, txs_keeped_by_block); diff --git a/tests/core_tests/integer_overflow.cpp b/tests/core_tests/integer_overflow.cpp index 3ac55c073..5a9604fc1 100644 --- a/tests/core_tests/integer_overflow.cpp +++ b/tests/core_tests/integer_overflow.cpp @@ -65,6 +65,7 @@ namespace se.real_output = 0; se.rct = false; se.real_out_tx_key = get_tx_pub_key_from_extra(tx); + se.real_out_additional_tx_keys = get_additional_tx_pub_keys_from_extra(tx); se.real_output_in_tx_index = out_idx; sources.push_back(se); @@ -175,7 +176,7 @@ bool gen_uint_overflow_2::generate(std::vector<test_event_entry>& events) const destinations.push_back(tx_destination_entry(sources.front().amount - MONEY_SUPPLY - MONEY_SUPPLY + 1 - TESTS_DEFAULT_FEE, bob_addr, false)); cryptonote::transaction tx_1; - if (!construct_tx(miner_account.get_keys(), sources, destinations, std::vector<uint8_t>(), tx_1, 0)) + if (!construct_tx(miner_account.get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), tx_1, 0)) return false; events.push_back(tx_1); @@ -201,7 +202,7 @@ bool gen_uint_overflow_2::generate(std::vector<test_event_entry>& events) const destinations.push_back(de); cryptonote::transaction tx_2; - if (!construct_tx(bob_account.get_keys(), sources, destinations, std::vector<uint8_t>(), tx_2, 0)) + if (!construct_tx(bob_account.get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), tx_2, 0)) return false; events.push_back(tx_2); diff --git a/tests/core_tests/transaction_tests.cpp b/tests/core_tests/transaction_tests.cpp index dcba36e80..00c602103 100644 --- a/tests/core_tests/transaction_tests.cpp +++ b/tests/core_tests/transaction_tests.cpp @@ -108,7 +108,7 @@ bool test_transaction_generation_and_ring_signature() destinations.push_back(td); transaction tx_rc1; - bool r = construct_tx(miner_acc2.get_keys(), sources, destinations, std::vector<uint8_t>(), tx_rc1, 0); + bool r = construct_tx(miner_acc2.get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), tx_rc1, 0); CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction"); crypto::hash pref_hash = get_transaction_prefix_hash(tx_rc1); diff --git a/tests/core_tests/v2_tests.cpp b/tests/core_tests/v2_tests.cpp index f1256cb64..6c94ac76c 100644 --- a/tests/core_tests/v2_tests.cpp +++ b/tests/core_tests/v2_tests.cpp @@ -108,7 +108,7 @@ bool gen_v2_tx_validation_base::generate_with(std::vector<test_event_entry>& eve destinations.push_back(td); transaction tx; - bool r = construct_tx(miner_accounts[0].get_keys(), sources, destinations, std::vector<uint8_t>(), tx, 0); + bool r = construct_tx(miner_accounts[0].get_keys(), sources, destinations, boost::none, std::vector<uint8_t>(), tx, 0); CHECK_AND_ASSERT_MES(r, false, "failed to construct transaction"); if (!valid) DO_CALLBACK(events, "mark_invalid_tx"); diff --git a/tests/libwallet_api_tests/main.cpp b/tests/libwallet_api_tests/main.cpp index a3cf227de..853ad7c8d 100644 --- a/tests/libwallet_api_tests/main.cpp +++ b/tests/libwallet_api_tests/main.cpp @@ -580,9 +580,9 @@ TEST_F(WalletTest1, WalletTransaction) PAYMENT_ID_EMPTY, AMOUNT_10XMR, MIXIN_COUNT, + Monero::PendingTransaction::Priority_Medium, 0, - std::set<uint32_t>{}, - Monero::PendingTransaction::Priority_Medium); + std::set<uint32_t>{}); ASSERT_TRUE(transaction->status() == Monero::PendingTransaction::Status_Ok); wallet1->refresh(); @@ -621,7 +621,7 @@ TEST_F(WalletTest1, WalletTransactionWithMixin) std::cerr << "Transaction mixin count: " << mixin << std::endl; Monero::PendingTransaction * transaction = wallet1->createTransaction( - recepient_address, payment_id, AMOUNT_5XMR, mixin, 0, std::set<uint32_t>{}); + recepient_address, payment_id, AMOUNT_5XMR, mixin, Monero::PendingTransaction::Priority_Medium, 0, std::set<uint32_t>{}); std::cerr << "Transaction status: " << transaction->status() << std::endl; std::cerr << "Transaction fee: " << Monero::Wallet::displayAmount(transaction->fee()) << std::endl; @@ -663,7 +663,7 @@ TEST_F(WalletTest1, WalletTransactionWithPriority) std::cerr << "Transaction priority: " << *it << std::endl; Monero::PendingTransaction * transaction = wallet1->createTransaction( - recepient_address, payment_id, AMOUNT_5XMR, mixin, 0, std::set<uint32_t>{}, *it); + recepient_address, payment_id, AMOUNT_5XMR, mixin, *it, 0, std::set<uint32_t>{}); std::cerr << "Transaction status: " << transaction->status() << std::endl; std::cerr << "Transaction fee: " << Monero::Wallet::displayAmount(transaction->fee()) << std::endl; std::cerr << "Transaction error: " << transaction->errorString() << std::endl; @@ -719,7 +719,7 @@ TEST_F(WalletTest1, WalletTransactionAndHistory) Monero::PendingTransaction * tx = wallet_src->createTransaction(wallet4_addr, PAYMENT_ID_EMPTY, - AMOUNT_10XMR * 5, 1, 0, std::set<uint32_t>{}); + AMOUNT_10XMR * 5, 1, Monero::PendingTransaction::Priority_Medium, 0, std::set<uint32_t>{}); ASSERT_TRUE(tx->status() == Monero::PendingTransaction::Status_Ok); ASSERT_TRUE(tx->commit()); @@ -761,7 +761,7 @@ TEST_F(WalletTest1, WalletTransactionWithPaymentId) Monero::PendingTransaction * tx = wallet_src->createTransaction(wallet4_addr, payment_id, - AMOUNT_1XMR, 1, 0, std::set<uint32_t>{}); + AMOUNT_1XMR, 1, Monero::PendingTransaction::Priority_Medium, 0, std::set<uint32_t>{}); ASSERT_TRUE(tx->status() == Monero::PendingTransaction::Status_Ok); ASSERT_TRUE(tx->commit()); @@ -934,7 +934,7 @@ TEST_F(WalletTest2, WalletCallbackSent) Monero::PendingTransaction * tx = wallet_src->createTransaction(wallet_dst->mainAddress(), PAYMENT_ID_EMPTY, - amount, 1, 0, std::set<uint32_t>{}); + amount, 1, Monero::PendingTransaction::Priority_Medium, 0, std::set<uint32_t>{}); std::cout << "** Committing transaction: " << Monero::Wallet::displayAmount(tx->amount()) << " with fee: " << Monero::Wallet::displayAmount(tx->fee()); @@ -975,7 +975,7 @@ TEST_F(WalletTest2, WalletCallbackReceived) std::cout << "** Sending " << Monero::Wallet::displayAmount(amount) << " to " << wallet_dst->mainAddress(); Monero::PendingTransaction * tx = wallet_src->createTransaction(wallet_dst->mainAddress(), PAYMENT_ID_EMPTY, - amount, 1, 0, std::set<uint32_t>{}); + amount, 1, Monero::PendingTransaction::Priority_Medium, 0, std::set<uint32_t>{}); std::cout << "** Committing transaction: " << Monero::Wallet::displayAmount(tx->amount()) << " with fee: " << Monero::Wallet::displayAmount(tx->fee()); diff --git a/tests/performance_tests/ge_frombytes_vartime.h b/tests/performance_tests/ge_frombytes_vartime.h index a5e64aeb2..ea72fcd26 100644 --- a/tests/performance_tests/ge_frombytes_vartime.h +++ b/tests/performance_tests/ge_frombytes_vartime.h @@ -54,7 +54,7 @@ public: std::vector<tx_destination_entry> destinations; destinations.push_back(tx_destination_entry(1, m_alice.get_keys().m_account_address, false)); - return construct_tx(this->m_miners[this->real_source_idx].get_keys(), this->m_sources, destinations, std::vector<uint8_t>(), m_tx, 0); + return construct_tx(this->m_miners[this->real_source_idx].get_keys(), this->m_sources, destinations, boost::none, std::vector<uint8_t>(), m_tx, 0); } bool test() diff --git a/tests/performance_tests/is_out_to_acc.h b/tests/performance_tests/is_out_to_acc.h index 7da061c1e..c31897628 100644 --- a/tests/performance_tests/is_out_to_acc.h +++ b/tests/performance_tests/is_out_to_acc.h @@ -64,6 +64,7 @@ public: { const cryptonote::txout_to_key& tx_out = boost::get<cryptonote::txout_to_key>(m_tx.vout[0].target); std::unordered_map<crypto::public_key, cryptonote::subaddress_index> subaddresses; + subaddresses[m_bob.get_keys().m_account_address.m_spend_public_key] = {0,0}; std::vector<crypto::key_derivation> additional_derivations; boost::optional<cryptonote::subaddress_receive_info> info = cryptonote::is_out_to_acc_precomp(subaddresses, tx_out.key, m_derivation, additional_derivations, 0); return (bool)info; diff --git a/tests/unit_tests/sha256.cpp b/tests/unit_tests/sha256.cpp index f4ad39466..0d657a1a9 100644 --- a/tests/unit_tests/sha256.cpp +++ b/tests/unit_tests/sha256.cpp @@ -28,8 +28,8 @@ #include "gtest/gtest.h" -#include "string_tools.h" #include "common/util.h" +#include "string_tools.h" static bool check(const std::string &data, const char *expected_hash_hex) { |