aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/dns_utils.cpp8
-rw-r--r--src/common/dns_utils.h2
-rw-r--r--src/cryptonote_basic/cryptonote_basic_impl.cpp6
-rw-r--r--src/cryptonote_basic/cryptonote_basic_impl.h2
-rw-r--r--src/p2p/net_node.h4
-rw-r--r--src/p2p/net_node.inl87
-rw-r--r--src/simplewallet/simplewallet.cpp8
-rw-r--r--src/version.h.in2
-rw-r--r--src/wallet/wallet2.cpp45
-rw-r--r--src/wallet/wallet_rpc_server.cpp28
-rw-r--r--src/wallet/wallet_rpc_server.h2
-rw-r--r--src/wallet/wallet_rpc_server_commands_defs.h15
12 files changed, 150 insertions, 59 deletions
diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp
index 7faf74dd8..ab38cbbae 100644
--- a/src/common/dns_utils.cpp
+++ b/src/common/dns_utils.cpp
@@ -405,21 +405,23 @@ std::vector<std::string> addresses_from_url(const std::string& url, bool& dnssec
return addresses;
}
-std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid)
+std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid, bool cli_confirm)
{
// attempt to get address from dns query
auto addresses = addresses_from_url(url, dnssec_valid);
if (addresses.empty())
{
- std::cout << tr("wrong address: ") << url;
+ LOG_ERROR("wrong address: " << url);
return {};
}
// for now, move on only if one address found
if (addresses.size() > 1)
{
- std::cout << tr("not yet supported: Multiple Monero addresses found for given URL: ") << url;
+ LOG_ERROR("not yet supported: Multiple Monero addresses found for given URL: " << url);
return {};
}
+ if (!cli_confirm)
+ return addresses[0];
// prompt user for confirmation.
// inform user of DNSSEC validation status as well.
std::string dnssec_str;
diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h
index 6a7fc5628..53c0c1c7b 100644
--- a/src/common/dns_utils.h
+++ b/src/common/dns_utils.h
@@ -163,7 +163,7 @@ namespace dns_utils
std::string address_from_txt_record(const std::string& s);
std::vector<std::string> addresses_from_url(const std::string& url, bool& dnssec_valid);
-std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid);
+std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid, bool cli_confirm = true);
bool load_txt_records_from_dns(std::vector<std::string> &records, const std::vector<std::string> &dns_urls);
diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp
index fb9e25c00..edd67793f 100644
--- a/src/cryptonote_basic/cryptonote_basic_impl.cpp
+++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp
@@ -308,12 +308,13 @@ namespace cryptonote {
, crypto::hash8& payment_id
, bool testnet
, const std::string& str_or_url
+ , bool cli_confirm
)
{
if (get_account_integrated_address_from_str(address, has_payment_id, payment_id, testnet, str_or_url))
return true;
bool dnssec_valid;
- std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(str_or_url, dnssec_valid);
+ std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(str_or_url, dnssec_valid, cli_confirm);
return !address_str.empty() &&
get_account_integrated_address_from_str(address, has_payment_id, payment_id, testnet, address_str);
}
@@ -322,11 +323,12 @@ namespace cryptonote {
cryptonote::account_public_address& address
, bool testnet
, const std::string& str_or_url
+ , bool cli_confirm
)
{
bool has_payment_id;
crypto::hash8 payment_id;
- return get_account_address_from_str_or_url(address, has_payment_id, payment_id, testnet, str_or_url);
+ return get_account_address_from_str_or_url(address, has_payment_id, payment_id, testnet, str_or_url, cli_confirm);
}
//--------------------------------------------------------------------------------
bool operator ==(const cryptonote::transaction& a, const cryptonote::transaction& b) {
diff --git a/src/cryptonote_basic/cryptonote_basic_impl.h b/src/cryptonote_basic/cryptonote_basic_impl.h
index 46974330b..4e1468510 100644
--- a/src/cryptonote_basic/cryptonote_basic_impl.h
+++ b/src/cryptonote_basic/cryptonote_basic_impl.h
@@ -107,12 +107,14 @@ namespace cryptonote {
, crypto::hash8& payment_id
, bool testnet
, const std::string& str_or_url
+ , bool cli_confirm = true
);
bool get_account_address_from_str_or_url(
cryptonote::account_public_address& address
, bool testnet
, const std::string& str_or_url
+ , bool cli_confirm = true
);
bool is_coinbase(const transaction& tx);
diff --git a/src/p2p/net_node.h b/src/p2p/net_node.h
index de0cf2c03..4582a3236 100644
--- a/src/p2p/net_node.h
+++ b/src/p2p/net_node.h
@@ -191,7 +191,6 @@ namespace nodetool
bool parse_peer_from_string(nodetool::net_address& pe, const std::string& node_addr);
bool handle_command_line(
const boost::program_options::variables_map& vm
- , bool testnet
);
bool idle_worker();
bool handle_remote_peerlist(const std::list<peerlist_entry>& peerlist, time_t local_time, const epee::net_utils::connection_context_base& context);
@@ -218,6 +217,7 @@ namespace nodetool
void cache_connect_fail_info(const net_address& addr);
bool is_addr_recently_failed(const net_address& addr);
bool is_priority_node(const net_address& na);
+ std::set<std::string> get_seed_nodes(bool testnet) const;
template <class Container>
bool connect_to_peerlist(const Container& peers);
@@ -321,6 +321,8 @@ namespace nodetool
epee::critical_section m_ip_fails_score_lock;
std::map<uint32_t, uint64_t> m_ip_fails_score;
+
+ bool m_testnet;
};
}
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index 99c4e9282..2e2dffab8 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -65,6 +65,7 @@
#define NET_MAKE_IP(b1,b2,b3,b4) ((LPARAM)(((DWORD)(b1)<<24)+((DWORD)(b2)<<16)+((DWORD)(b3)<<8)+((DWORD)(b4))))
+#define MIN_WANTED_SEED_NODES 12
namespace nodetool
{
@@ -287,10 +288,9 @@ namespace nodetool
template<class t_payload_net_handler>
bool node_server<t_payload_net_handler>::handle_command_line(
const boost::program_options::variables_map& vm
- , bool testnet
)
{
- auto p2p_bind_arg = testnet ? arg_testnet_p2p_bind_port : arg_p2p_bind_port;
+ auto p2p_bind_arg = m_testnet ? arg_testnet_p2p_bind_port : arg_p2p_bind_port;
m_bind_ip = command_line::get_arg(vm, arg_p2p_bind_ip);
m_port = command_line::get_arg(vm, p2p_bind_arg);
@@ -309,7 +309,7 @@ namespace nodetool
bool r = parse_peer_from_string(pe.adr, pr_str);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str);
if (pe.adr.port == 0)
- pe.adr.port = testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT;
+ pe.adr.port = m_testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT;
m_command_line_peers.push_back(pe);
}
}
@@ -398,14 +398,11 @@ namespace nodetool
//-----------------------------------------------------------------------------------
template<class t_payload_net_handler>
- bool node_server<t_payload_net_handler>::init(const boost::program_options::variables_map& vm)
+ std::set<std::string> node_server<t_payload_net_handler>::get_seed_nodes(bool testnet) const
{
std::set<std::string> full_addrs;
- bool testnet = command_line::get_arg(vm, command_line::arg_testnet_on);
-
if (testnet)
{
- memcpy(&m_network_id, &::config::testnet::NETWORK_ID, 16);
full_addrs.insert("212.83.175.67:28080");
full_addrs.insert("5.9.100.248:28080");
full_addrs.insert("163.172.182.165:28080");
@@ -414,6 +411,32 @@ namespace nodetool
}
else
{
+ full_addrs.insert("107.152.130.98:18080");
+ full_addrs.insert("212.83.175.67:18080");
+ full_addrs.insert("5.9.100.248:18080");
+ full_addrs.insert("163.172.182.165:18080");
+ full_addrs.insert("161.67.132.39:18080");
+ full_addrs.insert("198.74.231.92:18080");
+ full_addrs.insert("195.154.123.123:28080");
+ full_addrs.insert("212.83.172.165:28080");
+ }
+ return full_addrs;
+ }
+
+ //-----------------------------------------------------------------------------------
+ template<class t_payload_net_handler>
+ bool node_server<t_payload_net_handler>::init(const boost::program_options::variables_map& vm)
+ {
+ std::set<std::string> full_addrs;
+ m_testnet = command_line::get_arg(vm, command_line::arg_testnet_on);
+
+ if (m_testnet)
+ {
+ memcpy(&m_network_id, &::config::testnet::NETWORK_ID, 16);
+ full_addrs = get_seed_nodes(true);
+ }
+ else
+ {
memcpy(&m_network_id, &::config::NETWORK_ID, 16);
// for each hostname in the seed nodes list, attempt to DNS resolve and
// add the result addresses as seed nodes
@@ -483,18 +506,16 @@ namespace nodetool
++i;
}
- if (!full_addrs.size())
+ // append the fallback nodes if we have too few seed nodes to start with
+ if (full_addrs.size() < MIN_WANTED_SEED_NODES)
{
- MINFO("DNS seed node lookup either timed out or failed, falling back to defaults");
-
- full_addrs.insert("107.152.130.98:18080");
- full_addrs.insert("212.83.175.67:18080");
- full_addrs.insert("5.9.100.248:18080");
- full_addrs.insert("163.172.182.165:18080");
- full_addrs.insert("161.67.132.39:18080");
- full_addrs.insert("198.74.231.92:18080");
- full_addrs.insert("195.154.123.123:28080");
- full_addrs.insert("212.83.172.165:28080");
+ if (full_addrs.empty())
+ MINFO("DNS seed node lookup either timed out or failed, falling back to defaults");
+ else
+ MINFO("Not enough DNS seed nodes found, using fallback defaults too");
+
+ for (const auto &peer: get_seed_nodes(false))
+ full_addrs.insert(peer);
}
}
@@ -505,14 +526,14 @@ namespace nodetool
}
MDEBUG("Number of seed nodes: " << m_seed_nodes.size());
- bool res = handle_command_line(vm, testnet);
+ bool res = handle_command_line(vm);
CHECK_AND_ASSERT_MES(res, false, "Failed to handle command line");
- auto config_arg = testnet ? command_line::arg_testnet_data_dir : command_line::arg_data_dir;
+ auto config_arg = m_testnet ? command_line::arg_testnet_data_dir : command_line::arg_data_dir;
m_config_folder = command_line::get_arg(vm, config_arg);
- if ((!testnet && m_port != std::to_string(::config::P2P_DEFAULT_PORT))
- || (testnet && m_port != std::to_string(::config::testnet::P2P_DEFAULT_PORT))) {
+ if ((!m_testnet && m_port != std::to_string(::config::P2P_DEFAULT_PORT))
+ || (m_testnet && m_port != std::to_string(::config::testnet::P2P_DEFAULT_PORT))) {
m_config_folder = m_config_folder + "/" + m_port;
}
@@ -1082,6 +1103,7 @@ namespace nodetool
{
size_t try_count = 0;
size_t current_index = crypto::rand<size_t>()%m_seed_nodes.size();
+ bool fallback_nodes_added = false;
while(true)
{
if(m_net_server.is_stop_signal_sent())
@@ -1091,8 +1113,22 @@ namespace nodetool
break;
if(++try_count > m_seed_nodes.size())
{
- MWARNING("Failed to connect to any of seed peers, continuing without seeds");
- break;
+ if (!fallback_nodes_added)
+ {
+ MWARNING("Failed to connect to any of seed peers, trying fallback seeds");
+ for (const auto &peer: get_seed_nodes(m_testnet))
+ {
+ MDEBUG("Fallback seed node: " << peer);
+ append_net_address(m_seed_nodes, peer);
+ }
+ fallback_nodes_added = true;
+ // continue for another few cycles
+ }
+ else
+ {
+ MWARNING("Failed to connect to any of seed peers, continuing without seeds");
+ break;
+ }
}
if(++current_index >= m_seed_nodes.size())
current_index = 0;
@@ -1654,7 +1690,6 @@ namespace nodetool
bool node_server<t_payload_net_handler>::parse_peers_and_add_to_container(const boost::program_options::variables_map& vm, const command_line::arg_descriptor<std::vector<std::string> > & arg, Container& container)
{
std::vector<std::string> perrs = command_line::get_arg(vm, arg);
- bool testnet = command_line::get_arg(vm, command_line::arg_testnet_on);
for(const std::string& pr_str: perrs)
{
@@ -1662,7 +1697,7 @@ namespace nodetool
bool r = parse_peer_from_string(na, pr_str);
CHECK_AND_ASSERT_MES(r, false, "Failed to parse address from string: " << pr_str);
if (na.port == 0)
- na.port = testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT;
+ na.port = m_testnet ? ::config::testnet::P2P_DEFAULT_PORT : ::config::P2P_DEFAULT_PORT;
container.push_back(na);
}
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 242b565a1..ba4ff6299 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -2298,6 +2298,12 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
break;
}
+ if (ptx_vector.empty())
+ {
+ fail_msg_writer() << tr("No outputs found, or daemon is not ready");
+ return true;
+ }
+
// if more than one tx necessary, prompt user to confirm
if (m_wallet->always_confirm_transfers() || ptx_vector.size() > 1)
{
@@ -2764,7 +2770,7 @@ bool simple_wallet::sweep_all(const std::vector<std::string> &args_)
if (ptx_vector.empty())
{
- fail_msg_writer() << tr("No outputs found");
+ fail_msg_writer() << tr("No outputs found, or daemon is not ready");
return true;
}
diff --git a/src/version.h.in b/src/version.h.in
index cfde3b0ee..fe699acdd 100644
--- a/src/version.h.in
+++ b/src/version.h.in
@@ -1,4 +1,4 @@
#define MONERO_VERSION_TAG "@VERSIONTAG@"
-#define MONERO_VERSION "0.10.2.1"
+#define MONERO_VERSION "0.10.2.2"
#define MONERO_RELEASE_NAME "Wolfram Warptangent"
#define MONERO_VERSION_FULL MONERO_VERSION "-" MONERO_VERSION_TAG
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 379159709..dff848a92 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -2639,28 +2639,31 @@ void wallet2::get_unconfirmed_payments(std::list<std::pair<crypto::hash,wallet2:
//----------------------------------------------------------------------------------------------------
void wallet2::rescan_spent()
{
- std::vector<std::string> key_images;
-
- // make a list of key images for all our outputs
- for (size_t i = 0; i < m_transfers.size(); ++i)
- {
- const transfer_details& td = m_transfers[i];
- key_images.push_back(string_tools::pod_to_hex(td.m_key_image));
+ // This is RPC call that can take a long time if there are many outputs,
+ // so we call it several times, in stripes, so we don't time out spuriously
+ std::vector<int> spent_status;
+ spent_status.reserve(m_transfers.size());
+ const size_t chunk_size = 1000;
+ for (size_t start_offset = 0; start_offset < m_transfers.size(); start_offset += chunk_size)
+ {
+ const size_t n_outputs = std::min<size_t>(chunk_size, m_transfers.size() - start_offset);
+ MDEBUG("Calling is_key_image_spent on " << start_offset << " - " << (start_offset + n_outputs - 1) << ", out of " << m_transfers.size());
+ COMMAND_RPC_IS_KEY_IMAGE_SPENT::request req = AUTO_VAL_INIT(req);
+ COMMAND_RPC_IS_KEY_IMAGE_SPENT::response daemon_resp = AUTO_VAL_INIT(daemon_resp);
+ for (size_t n = start_offset; n < start_offset + n_outputs; ++n)
+ req.key_images.push_back(string_tools::pod_to_hex(m_transfers[n].m_key_image));
+ m_daemon_rpc_mutex.lock();
+ bool r = epee::net_utils::invoke_http_json("/is_key_image_spent", req, daemon_resp, m_http_client, rpc_timeout);
+ m_daemon_rpc_mutex.unlock();
+ THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "is_key_image_spent");
+ THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "is_key_image_spent");
+ THROW_WALLET_EXCEPTION_IF(daemon_resp.status != CORE_RPC_STATUS_OK, error::is_key_image_spent_error, daemon_resp.status);
+ THROW_WALLET_EXCEPTION_IF(daemon_resp.spent_status.size() != n_outputs, error::wallet_internal_error,
+ "daemon returned wrong response for is_key_image_spent, wrong amounts count = " +
+ std::to_string(daemon_resp.spent_status.size()) + ", expected " + std::to_string(n_outputs));
+ std::copy(daemon_resp.spent_status.begin(), daemon_resp.spent_status.end(), std::back_inserter(spent_status));
}
- COMMAND_RPC_IS_KEY_IMAGE_SPENT::request req = AUTO_VAL_INIT(req);
- COMMAND_RPC_IS_KEY_IMAGE_SPENT::response daemon_resp = AUTO_VAL_INIT(daemon_resp);
- req.key_images = key_images;
- m_daemon_rpc_mutex.lock();
- bool r = epee::net_utils::invoke_http_json("/is_key_image_spent", req, daemon_resp, m_http_client, rpc_timeout);
- m_daemon_rpc_mutex.unlock();
- THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "is_key_image_spent");
- THROW_WALLET_EXCEPTION_IF(daemon_resp.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "is_key_image_spent");
- THROW_WALLET_EXCEPTION_IF(daemon_resp.status != CORE_RPC_STATUS_OK, error::is_key_image_spent_error, daemon_resp.status);
- THROW_WALLET_EXCEPTION_IF(daemon_resp.spent_status.size() != key_images.size(), error::wallet_internal_error,
- "daemon returned wrong response for is_key_image_spent, wrong amounts count = " +
- std::to_string(daemon_resp.spent_status.size()) + ", expected " + std::to_string(key_images.size()));
-
// update spent status
for (size_t i = 0; i < m_transfers.size(); ++i)
{
@@ -2668,7 +2671,7 @@ void wallet2::rescan_spent()
// a view wallet may not know about key images
if (!td.m_key_image_known)
continue;
- if (td.m_spent != (daemon_resp.spent_status[i] != COMMAND_RPC_IS_KEY_IMAGE_SPENT::UNSPENT))
+ if (td.m_spent != (spent_status[i] != COMMAND_RPC_IS_KEY_IMAGE_SPENT::UNSPENT))
{
if (td.m_spent)
{
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index 55a22df49..9002048c8 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -300,7 +300,7 @@ namespace tools
cryptonote::tx_destination_entry de;
bool has_payment_id;
crypto::hash8 new_payment_id;
- if(!get_account_integrated_address_from_str(de.addr, has_payment_id, new_payment_id, m_wallet.testnet(), it->address))
+ if(!get_account_address_from_str_or_url(de.addr, has_payment_id, new_payment_id, m_wallet.testnet(), it->address, false))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
er.message = std::string("WALLET_RPC_ERROR_CODE_WRONG_ADDRESS: ") + it->address;
@@ -945,7 +945,7 @@ namespace tools
cryptonote::account_public_address address;
bool has_payment_id;
crypto::hash8 payment_id;
- if(!get_account_integrated_address_from_str(address, has_payment_id, payment_id, m_wallet.testnet(), req.address))
+ if(!get_account_address_from_str_or_url(address, has_payment_id, payment_id, m_wallet.testnet(), req.address, false))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
er.message = "";
@@ -1308,7 +1308,7 @@ namespace tools
bool has_payment_id;
crypto::hash8 payment_id8;
crypto::hash payment_id = cryptonote::null_hash;
- if(!get_account_integrated_address_from_str(address, has_payment_id, payment_id8, m_wallet.testnet(), req.address))
+ if(!get_account_address_from_str_or_url(address, has_payment_id, payment_id8, m_wallet.testnet(), req.address, false))
{
er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS;
er.message = std::string("WALLET_RPC_ERROR_CODE_WRONG_ADDRESS: ") + req.address;
@@ -1374,6 +1374,28 @@ namespace tools
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
+ bool wallet_rpc_server::on_rescan_spent(const wallet_rpc::COMMAND_RPC_RESCAN_SPENT::request& req, wallet_rpc::COMMAND_RPC_RESCAN_SPENT::response& res, epee::json_rpc::error& er)
+ {
+ if (m_wallet.restricted())
+ {
+ er.code = WALLET_RPC_ERROR_CODE_DENIED;
+ er.message = "Command unavailable in restricted mode.";
+ return false;
+ }
+ try
+ {
+ m_wallet.rescan_spent();
+ return true;
+ }
+ catch (const std::exception &e)
+ {
+ er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
+ er.message = e.what();
+ return false;
+ }
+ return true;
+ }
+ //------------------------------------------------------------------------------------------------------------------------------
}
int main(int argc, char** argv) {
diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h
index c43c595df..7dd07d12f 100644
--- a/src/wallet/wallet_rpc_server.h
+++ b/src/wallet/wallet_rpc_server.h
@@ -92,6 +92,7 @@ namespace tools
MAP_JON_RPC_WE("get_address_book", on_get_address_book, wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY)
MAP_JON_RPC_WE("add_address_book", on_add_address_book, wallet_rpc::COMMAND_RPC_ADD_ADDRESS_BOOK_ENTRY)
MAP_JON_RPC_WE("delete_address_book",on_delete_address_book,wallet_rpc::COMMAND_RPC_DELETE_ADDRESS_BOOK_ENTRY)
+ MAP_JON_RPC_WE("rescan_spent", on_rescan_spent, wallet_rpc::COMMAND_RPC_RESCAN_SPENT)
END_JSON_RPC_MAP()
END_URI_MAP2()
@@ -125,6 +126,7 @@ namespace tools
bool on_get_address_book(const wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::request& req, wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::response& res, epee::json_rpc::error& er);
bool on_add_address_book(const wallet_rpc::COMMAND_RPC_ADD_ADDRESS_BOOK_ENTRY::request& req, wallet_rpc::COMMAND_RPC_ADD_ADDRESS_BOOK_ENTRY::response& res, epee::json_rpc::error& er);
bool on_delete_address_book(const wallet_rpc::COMMAND_RPC_DELETE_ADDRESS_BOOK_ENTRY::request& req, wallet_rpc::COMMAND_RPC_DELETE_ADDRESS_BOOK_ENTRY::response& res, epee::json_rpc::error& er);
+ bool on_rescan_spent(const wallet_rpc::COMMAND_RPC_RESCAN_SPENT::request& req, wallet_rpc::COMMAND_RPC_RESCAN_SPENT::response& res, epee::json_rpc::error& er);
//json rpc v2
bool on_query_key(const wallet_rpc::COMMAND_RPC_QUERY_KEY::request& req, wallet_rpc::COMMAND_RPC_QUERY_KEY::response& res, epee::json_rpc::error& er);
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
index 78f896f16..2ec965b4d 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -857,5 +857,20 @@ namespace wallet_rpc
};
};
+ struct COMMAND_RPC_RESCAN_SPENT
+ {
+ struct request
+ {
+ BEGIN_KV_SERIALIZE_MAP()
+ END_KV_SERIALIZE_MAP()
+ };
+
+ struct response
+ {
+ BEGIN_KV_SERIALIZE_MAP()
+ END_KV_SERIALIZE_MAP()
+ };
+ };
+
}
}