aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet2.cpp
diff options
context:
space:
mode:
authorHoward Chu <hyc@symas.com>2016-04-13 23:45:02 +0100
committerHoward Chu <hyc@symas.com>2016-04-17 15:25:46 +0100
commitb7140daea2b33d03f65b852de7f1ce4b99661adf (patch)
treeadbf2b2738cb198ac2122f9640e7e480317bfe86 /src/wallet/wallet2.cpp
parentMerge pull request #803 (diff)
downloadmonero-b7140daea2b33d03f65b852de7f1ce4b99661adf.tar.xz
Add GET_HASHES_FAST rpc, use it in wallet
When m_refresh_from_block_height has been set, only hashes will be retrieved up to that height, instead of full blocks. The same will be done for "refresh <height>" when the specified height is beyond the current local blockchain.
Diffstat (limited to 'src/wallet/wallet2.cpp')
-rw-r--r--src/wallet/wallet2.cpp87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 14da8d7a2..1c1e386ca 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -578,6 +578,24 @@ void wallet2::pull_blocks(uint64_t start_height, uint64_t &blocks_start_height,
blocks = res.blocks;
}
//----------------------------------------------------------------------------------------------------
+void wallet2::pull_hashes(uint64_t start_height, uint64_t &blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::list<crypto::hash> &hashes)
+{
+ cryptonote::COMMAND_RPC_GET_HASHES_FAST::request req = AUTO_VAL_INIT(req);
+ cryptonote::COMMAND_RPC_GET_HASHES_FAST::response res = AUTO_VAL_INIT(res);
+ req.block_ids = short_chain_history;
+
+ req.start_height = start_height;
+ m_daemon_rpc_mutex.lock();
+ bool r = net_utils::invoke_http_bin_remote_command2(m_daemon_address + "/gethashes.bin", req, res, m_http_client, WALLET_RCP_CONNECTION_TIMEOUT);
+ m_daemon_rpc_mutex.unlock();
+ THROW_WALLET_EXCEPTION_IF(!r, error::no_connection_to_daemon, "gethashes.bin");
+ THROW_WALLET_EXCEPTION_IF(res.status == CORE_RPC_STATUS_BUSY, error::daemon_busy, "gethashes.bin");
+ THROW_WALLET_EXCEPTION_IF(res.status != CORE_RPC_STATUS_OK, error::get_hashes_error, res.status);
+
+ blocks_start_height = res.start_height;
+ hashes = res.m_block_ids;
+}
+//----------------------------------------------------------------------------------------------------
void wallet2::process_blocks(uint64_t start_height, const std::list<cryptonote::block_complete_entry> &blocks, uint64_t& blocks_added)
{
size_t current_index = start_height;
@@ -772,6 +790,60 @@ void wallet2::check_pending_txes()
}
}
//----------------------------------------------------------------------------------------------------
+void wallet2::fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history)
+{
+ std::list<crypto::hash> hashes;
+ size_t current_index = m_blockchain.size();
+ while(current_index < stop_height)
+ {
+ pull_hashes(0, blocks_start_height, short_chain_history, hashes);
+ if (hashes.size() < 3)
+ return;
+ if (hashes.size() + current_index < stop_height) {
+ std::list<crypto::hash>::iterator right;
+ // drop early 3 off, skipping the genesis block
+ if (short_chain_history.size() > 3) {
+ right = short_chain_history.end();
+ std::advance(right,-1);
+ std::list<crypto::hash>::iterator left = right;
+ std::advance(left, -3);
+ short_chain_history.erase(left, right);
+ }
+ right = hashes.end();
+ // prepend 3 more
+ for (int i = 0; i<3; i++) {
+ right--;
+ short_chain_history.push_front(*right);
+ }
+ }
+ current_index = blocks_start_height;
+ BOOST_FOREACH(auto& bl_id, hashes)
+ {
+ if(current_index >= m_blockchain.size())
+ {
+ LOG_PRINT_L2( "Skipped block by height: " << current_index);
+ m_blockchain.push_back(bl_id);
+ ++m_local_bc_height;
+
+ if (0 != m_callback)
+ { // FIXME: this isn't right, but simplewallet just logs that we got a block.
+ cryptonote::block dummy;
+ m_callback->on_new_block(current_index, dummy);
+ }
+ }
+ else if(bl_id != m_blockchain[current_index])
+ {
+ //split detected here !!!
+ return;
+ }
+ ++current_index;
+ if (current_index >= stop_height)
+ return;
+ }
+ }
+}
+
+//----------------------------------------------------------------------------------------------------
void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& received_money)
{
received_money = false;
@@ -786,7 +858,22 @@ void wallet2::refresh(uint64_t start_height, uint64_t & blocks_fetched, bool& re
// pull the first set of blocks
get_short_chain_history(short_chain_history);
+ if (start_height > m_blockchain.size() || m_refresh_from_block_height > m_blockchain.size()) {
+ if (!start_height)
+ start_height = m_refresh_from_block_height;
+ // we can shortcut by only pulling hashes up to the start_height
+ fast_refresh(start_height, blocks_start_height, short_chain_history);
+ // regenerate the history now that we've got a full set of hashes
+ short_chain_history.clear();
+ get_short_chain_history(short_chain_history);
+ start_height = 0;
+ // and then fall through to regular refresh processing
+ }
+
pull_blocks(start_height, blocks_start_height, short_chain_history, blocks);
+ // always reset start_height to 0 to force short_chain_ history to be used on
+ // subsequent pulls in this refresh.
+ start_height = 0;
m_run.store(true, std::memory_order_relaxed);
while(m_run.load(std::memory_order_relaxed))