aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2017-03-18 12:46:09 +0000
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2017-03-18 12:47:07 +0000
commit3fa5975520803bca9c9d6749eb2c2e6ced6a6cd8 (patch)
tree74527643f0e9965a0d021feae5f81d414045b0e9
parentwallet_rpc_server: add a rescan_spent RPC (diff)
downloadmonero-3fa5975520803bca9c9d6749eb2c2e6ced6a6cd8.tar.xz
wallet2: call is_key_image_spent in blocks in rescan_spent
This is a potentially long lasting daemon RPC call
-rw-r--r--src/wallet/wallet2.cpp45
1 files changed, 24 insertions, 21 deletions
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)
{