aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md4
-rwxr-xr-x[-rw-r--r--]contrib/epee/include/net/http_base.h3
-rwxr-xr-x[-rw-r--r--]contrib/epee/include/net/http_client.h12
-rwxr-xr-x[-rw-r--r--]contrib/epee/include/net/http_protocol_handler.h2
-rwxr-xr-x[-rw-r--r--]contrib/epee/include/net/http_protocol_handler.inl55
-rwxr-xr-x[-rw-r--r--]contrib/epee/include/net/http_server_handlers_map2.h0
-rwxr-xr-x[-rw-r--r--]contrib/epee/include/net/http_server_impl_base.h5
-rw-r--r--contrib/epee/include/net/net_helper.h10
-rw-r--r--src/blockchain_db/lmdb/db_lmdb.cpp6
-rw-r--r--src/blockchain_utilities/CMakeLists.txt2
-rw-r--r--src/cryptonote_config.h2
-rw-r--r--src/cryptonote_core/blockchain.cpp35
-rwxr-xr-x[-rw-r--r--]src/rpc/core_rpc_server.cpp2
-rwxr-xr-x[-rw-r--r--]src/rpc/rpc_args.cpp18
-rwxr-xr-x[-rw-r--r--]src/rpc/rpc_args.h2
-rw-r--r--src/wallet/api/wallet.cpp3
-rw-r--r--src/wallet/api/wallet.h12
-rw-r--r--src/wallet/wallet2.cpp24
-rw-r--r--src/wallet/wallet2.h19
-rw-r--r--src/wallet/wallet2_api.h12
-rwxr-xr-x[-rw-r--r--]src/wallet/wallet_rpc_server.cpp189
-rw-r--r--src/wallet/wallet_rpc_server.h1
-rw-r--r--src/wallet/wallet_rpc_server_error_codes.h8
-rw-r--r--tests/libwallet_api_tests/main.cpp16
24 files changed, 276 insertions, 166 deletions
diff --git a/README.md b/README.md
index f9c52a6d8..a392cfe95 100644
--- a/README.md
+++ b/README.md
@@ -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 e0d80f964..ee0e13fc1 100644
--- a/contrib/epee/include/net/net_helper.h
+++ b/contrib/epee/include/net/net_helper.h
@@ -383,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))
@@ -464,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))
@@ -607,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/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/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/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());