aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/wallet2.cpp
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-04-28 12:11:42 +0100
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-07-16 23:13:56 +0100
commitd6440ab319ea6adf21485550d6a08ae452d49818 (patch)
tree3829a4d28fc531c672c23337be702172c7d7f9a7 /src/wallet/wallet2.cpp
parentMerge pull request #4117 (diff)
downloadmonero-d6440ab319ea6adf21485550d6a08ae452d49818.tar.xz
wallet2: recover from index out of hashchain bounds error
This can happen when there's a very large reorg on the daemon (ie, on testnet)
Diffstat (limited to '')
-rw-r--r--src/wallet/wallet2.cpp36
1 files changed, 32 insertions, 4 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 40a43b8e7..66188b823 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -1823,7 +1823,7 @@ void wallet2::process_parsed_blocks(uint64_t start_height, const std::vector<cry
blocks_added = 0;
THROW_WALLET_EXCEPTION_IF(blocks.size() != parsed_blocks.size(), error::wallet_internal_error, "size mismatch");
- THROW_WALLET_EXCEPTION_IF(!m_blockchain.is_in_bounds(current_index), error::wallet_internal_error, "Index out of bounds of hashchain");
+ THROW_WALLET_EXCEPTION_IF(!m_blockchain.is_in_bounds(current_index), error::out_of_hashchain_bounds_error);
tools::threadpool& tpool = tools::threadpool::getInstance();
tools::threadpool::waiter waiter;
@@ -2269,12 +2269,12 @@ void wallet2::update_pool_state(bool refreshed)
MDEBUG("update_pool_state end");
}
//----------------------------------------------------------------------------------------------------
-void wallet2::fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history)
+void wallet2::fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list<crypto::hash> &short_chain_history, bool force)
{
std::vector<crypto::hash> hashes;
const uint64_t checkpoint_height = m_checkpoints.get_max_height();
- if (stop_height > checkpoint_height && m_blockchain.size()-1 < checkpoint_height)
+ if ((stop_height > checkpoint_height && m_blockchain.size()-1 < checkpoint_height) && !force)
{
// we will drop all these, so don't bother getting them
uint64_t missing_blocks = m_checkpoints.get_max_height() - m_blockchain.size();
@@ -2439,6 +2439,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
std::vector<cryptonote::block_complete_entry> next_blocks;
std::vector<parsed_block> next_parsed_blocks;
bool error = false;
+ added_blocks = 0;
if (!first && blocks.empty())
{
refreshed = false;
@@ -2448,7 +2449,33 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
if (!first)
{
- process_parsed_blocks(blocks_start_height, blocks, parsed_blocks, added_blocks);
+ try
+ {
+ process_parsed_blocks(blocks_start_height, blocks, parsed_blocks, added_blocks);
+ }
+ catch (const tools::error::out_of_hashchain_bounds_error&)
+ {
+ MINFO("Daemon claims next refresh block is out of hash chain bounds, resetting hash chain");
+ uint64_t stop_height = m_blockchain.offset();
+ std::vector<crypto::hash> tip(m_blockchain.size() - m_blockchain.offset());
+ for (size_t i = m_blockchain.offset(); i < m_blockchain.size(); ++i)
+ tip[i - m_blockchain.offset()] = m_blockchain[i];
+ cryptonote::block b;
+ generate_genesis(b);
+ m_blockchain.clear();
+ m_blockchain.push_back(get_block_hash(b));
+ short_chain_history.clear();
+ get_short_chain_history(short_chain_history);
+ fast_refresh(stop_height, blocks_start_height, short_chain_history, true);
+ THROW_WALLET_EXCEPTION_IF(m_blockchain.size() != stop_height, error::wallet_internal_error, "Unexpected hashchain size");
+ THROW_WALLET_EXCEPTION_IF(m_blockchain.offset() != 0, error::wallet_internal_error, "Unexpected hashchain offset");
+ for (const auto &h: tip)
+ m_blockchain.push_back(h);
+ short_chain_history.clear();
+ get_short_chain_history(short_chain_history);
+ start_height = stop_height;
+ throw std::runtime_error(""); // loop again
+ }
blocks_fetched += added_blocks;
}
waiter.wait(&tpool);
@@ -2478,6 +2505,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
if(try_count < 3)
{
LOG_PRINT_L1("Another try pull_blocks (try_count=" << try_count << ")...");
+ first = true;
++try_count;
}
else