diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/dns_utils.cpp | 8 | ||||
-rw-r--r-- | src/common/dns_utils.h | 2 | ||||
-rw-r--r-- | src/cryptonote_basic/cryptonote_basic_impl.cpp | 6 | ||||
-rw-r--r-- | src/cryptonote_basic/cryptonote_basic_impl.h | 2 | ||||
-rw-r--r-- | src/p2p/net_node.h | 4 | ||||
-rw-r--r-- | src/p2p/net_node.inl | 87 | ||||
-rw-r--r-- | src/simplewallet/simplewallet.cpp | 8 | ||||
-rw-r--r-- | src/version.h.in | 2 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 45 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server.cpp | 28 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server.h | 2 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server_commands_defs.h | 15 |
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() + }; + }; + } } |