diff options
Diffstat (limited to 'src/wallet')
-rw-r--r-- | src/wallet/api/pending_transaction.cpp | 2 | ||||
-rw-r--r-- | src/wallet/api/wallet.cpp | 2 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 45 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server.cpp | 72 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server.h | 2 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server_commands_defs.h | 15 |
6 files changed, 104 insertions, 34 deletions
diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp index 60edc95ce..9798d66c6 100644 --- a/src/wallet/api/pending_transaction.cpp +++ b/src/wallet/api/pending_transaction.cpp @@ -124,7 +124,7 @@ bool PendingTransactionImpl::commit(const std::string &filename, bool overwrite) m_errorString = writer.str(); if (!reason.empty()) m_errorString += string(tr(". Reason: ")) + reason; - } catch (std::exception &e) { + } catch (const std::exception &e) { m_errorString = string(tr("Unknown exception: ")) + e.what(); m_status = Status_Error; } catch (...) { diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index 963bbe0ab..d5c2fbda2 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -833,7 +833,7 @@ bool WalletImpl::exportKeyImages(const string &filename) return false; } } - catch (std::exception &e) + catch (const std::exception &e) { LOG_ERROR("Error exporting key images: " << e.what()); m_errorString = e.what(); 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 be8e0057d..84b15e021 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -252,7 +252,7 @@ namespace tools res.balance = m_wallet.balance(); res.unlocked_balance = m_wallet.unlocked_balance(); } - catch (std::exception& e) + catch (const std::exception& e) { er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; er.message = e.what(); @@ -267,7 +267,7 @@ namespace tools { res.address = m_wallet.get_account().get_public_address_str(m_wallet.testnet()); } - catch (std::exception& e) + catch (const std::exception& e) { er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; er.message = e.what(); @@ -282,7 +282,7 @@ namespace tools { res.height = m_wallet.get_blockchain_current_height(); } - catch (std::exception& e) + catch (const std::exception& e) { er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; er.message = e.what(); @@ -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; @@ -636,7 +636,7 @@ namespace tools res.payment_id = epee::string_tools::pod_to_hex(payment_id); return true; } - catch (std::exception &e) + catch (const std::exception &e) { er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; er.message = e.what(); @@ -669,7 +669,7 @@ namespace tools res.payment_id = epee::string_tools::pod_to_hex(payment_id); return true; } - catch (std::exception &e) + catch (const std::exception &e) { er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; er.message = e.what(); @@ -691,7 +691,7 @@ namespace tools { m_wallet.store(); } - catch (std::exception& e) + catch (const std::exception& e) { er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; er.message = e.what(); @@ -911,7 +911,7 @@ namespace tools { m_wallet.rescan_blockchain(); } - catch (std::exception& e) + catch (const std::exception& e) { er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; er.message = e.what(); @@ -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 = ""; @@ -970,7 +970,7 @@ namespace tools m_wallet.store(); m_stop.store(true, std::memory_order_relaxed); } - catch (std::exception& e) + catch (const std::exception& e) { er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; er.message = e.what(); @@ -981,6 +981,13 @@ namespace tools //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_set_tx_notes(const wallet_rpc::COMMAND_RPC_SET_TX_NOTES::request& req, wallet_rpc::COMMAND_RPC_SET_TX_NOTES::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; + } + if (req.txids.size() != req.notes.size()) { er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; @@ -1208,6 +1215,13 @@ namespace tools //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_import_key_images(const wallet_rpc::COMMAND_RPC_IMPORT_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_IMPORT_KEY_IMAGES::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 { std::vector<std::pair<crypto::key_image, crypto::signature>> ski; @@ -1304,11 +1318,18 @@ namespace tools //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::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) { + if (m_wallet.restricted()) + { + er.code = WALLET_RPC_ERROR_CODE_DENIED; + er.message = "Command unavailable in restricted mode."; + return false; + } + cryptonote::account_public_address address; 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; @@ -1358,6 +1379,13 @@ namespace tools //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::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) { + if (m_wallet.restricted()) + { + er.code = WALLET_RPC_ERROR_CODE_DENIED; + er.message = "Command unavailable in restricted mode."; + return false; + } + const auto ab = m_wallet.get_address_book(); if (req.index >= ab.size()) { @@ -1374,6 +1402,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() + }; + }; + } } |