diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 5e89ae22..26a0e24d 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1263,6 +1263,7 @@ void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic& stop if (full_reset_needed) { last_matched_index = 0; + been_matched_block = true; } else { @@ -1271,7 +1272,7 @@ void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic& stop } //TODO: take into account date of wallet creation //reorganize - detach_blockchain(last_matched_index); + detach_blockchain(last_matched_index+1); process_new_blockchain_entry(bl, bl_entry, bl_id, height); ++blocks_added; } @@ -1777,23 +1778,23 @@ bool wallet2::refresh(size_t & blocks_fetched, bool& received_money, bool& ok, s } //---------------------------------------------------------------------------------------------------- -uint64_t wallet2::detach_from_block_ids(uint64_t height) +uint64_t wallet2::detach_from_block_ids(uint64_t including_height) { //calculate number of erased blocks - uint64_t blocks_detached = (get_blockchain_current_size() -1 ) - height; + uint64_t blocks_detached = get_blockchain_current_size() - including_height; //id at height should be kept, the rest - erased - m_chain.detach(height); + m_chain.detach(including_height); return blocks_detached; } //---------------------------------------------------------------------------------------------------- -void wallet2::detach_blockchain(uint64_t height) +void wallet2::detach_blockchain(uint64_t including_height) { - WLT_LOG_L0("Detaching blockchain on height " << height); + WLT_LOG_L0("Detaching blockchain on height " << including_height); size_t transfers_detached = 0; // rollback incoming transfers from detaching subchain { - auto it = std::find_if(m_transfers.begin(), m_transfers.end(), [&](const transfer_details& td){return td.m_ptx_wallet_info->m_block_height >= height; }); + auto it = std::find_if(m_transfers.begin(), m_transfers.end(), [&](const transfer_details& td){return td.m_ptx_wallet_info->m_block_height >= including_height; }); if (it != m_transfers.end()) { size_t i_start = it - m_transfers.begin(); @@ -1802,7 +1803,7 @@ void wallet2::detach_blockchain(uint64_t height) { auto it_ki = m_key_images.find(m_transfers[i].m_key_image); WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it_ki != m_key_images.end(), "key image " << m_transfers[i].m_key_image << " not found"); - WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(m_transfers[i].m_ptx_wallet_info->m_block_height >= height, "transfer #" << i << " block height is less than " << height); + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(m_transfers[i].m_ptx_wallet_info->m_block_height >= including_height, "transfer #" << i << " block height is less than " << including_height); m_key_images.erase(it_ki); ++transfers_detached; } @@ -1810,7 +1811,7 @@ void wallet2::detach_blockchain(uint64_t height) } } - size_t blocks_detached = detach_from_block_ids(height); + size_t blocks_detached = detach_from_block_ids(including_height); //rollback spends // do not clear spent flag in spent transfers as corresponding txs are most likely in the pool @@ -1818,7 +1819,7 @@ void wallet2::detach_blockchain(uint64_t height) for (size_t i = 0, sz = m_transfers.size(); i < sz; ++i) { auto& tr = m_transfers[i]; - if (tr.m_spent_height >= height) + if (tr.m_spent_height >= including_height) { WLT_LOG_BLUE("Transfer [" << i << "] spent height: " << tr.m_spent_height << " -> 0, reason: detaching blockchain", LOG_LEVEL_1); tr.m_spent_height = 0; @@ -1829,7 +1830,7 @@ void wallet2::detach_blockchain(uint64_t height) auto tr_hist_it = m_transfer_history.rend(); for (auto it = m_transfer_history.rbegin(); it != m_transfer_history.rend(); it++) { - if (it->height < height) + if (it->height < including_height) break; tr_hist_it = it; // note that tr_hist_it->height >= height } @@ -1859,13 +1860,13 @@ void wallet2::detach_blockchain(uint64_t height) //rollback payments for (auto it = m_payments.begin(); it != m_payments.end(); ) { - if(height <= it->second.m_block_height) + if(including_height <= it->second.m_block_height) it = m_payments.erase(it); else ++it; } - WLT_LOG_L0("Detached blockchain on height " << height << ", transfers detached " << transfers_detached << ", blocks detached " << blocks_detached); + WLT_LOG_L0("Detached blockchain on height " << including_height << ", transfers detached " << transfers_detached << ", blocks detached " << blocks_detached); } //---------------------------------------------------------------------------------------------------- bool wallet2::deinit() diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index a9e214f3..2e9a55e3 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -785,7 +785,7 @@ private: void remove_transfer_from_expiration_list(uint64_t transfer_index); void load_keys(const std::string& keys_file_name, const std::string& password); void process_new_transaction(const currency::transaction& tx, uint64_t height, const currency::block& b); - void detach_blockchain(uint64_t height); + void detach_blockchain(uint64_t including_height); bool extract_offers_from_transfer_entry(size_t i, std::unordered_map& offers_local); bool select_my_offers(std::list& offers); bool clear(); diff --git a/src/wallet/wallet_chain_shortener.cpp b/src/wallet/wallet_chain_shortener.cpp index 3d3bba28..c89b100d 100644 --- a/src/wallet/wallet_chain_shortener.cpp +++ b/src/wallet/wallet_chain_shortener.cpp @@ -52,6 +52,12 @@ const crypto::hash& wallet_chain_shortener::get_genesis() //---------------------------------------------------------------------------------------------------- void wallet_chain_shortener::push_new_block_id(const crypto::hash& id, uint64_t height) { + if (height == 0) + { + m_genesis = id; + m_local_bc_size = 1; + return; + } //primary 10 //self check @@ -195,6 +201,25 @@ bool wallet_chain_shortener::lookup_item_around(uint64_t i, std::pair 0) + { + block_found = true; + block_matched = id == m_genesis; + if (!block_matched) { + full_reset_needed = true; + } + } + else + { + block_found = false; + block_matched = false; + full_reset_needed = true; + } + return; + } if (!m_last_20_blocks.empty() && i > m_last_20_blocks.begin()->first) { //must be in short sequence (m_last_20_blocks) @@ -221,7 +246,7 @@ void wallet_chain_shortener::check_if_block_matched(uint64_t i, const crypto::ha bool r = lookup_item_around(i, result); if (!r) { - LOG_PRINT_L0("Wallet is getting fully resynced due to unmatched block " << id << " at " << i); + LOG_PRINT_L0("Wallet is getting fully resynced due to lookup_item_around failed at " << i); block_matched = block_found = false; full_reset_needed = true; return; @@ -251,17 +276,17 @@ void wallet_chain_shortener::check_if_block_matched(uint64_t i, const crypto::ha //---------------------------------------------------------------------------------------------------- void clean_map_from_items_above(std::map& container, uint64_t height) { - while (container.size() && (--container.end())->first > height) + while (container.size() && (--container.end())->first >= height) { container.erase(--container.end()); } } //---------------------------------------------------------------------------------------------------- -void wallet_chain_shortener::detach(uint64_t height) +void wallet_chain_shortener::detach(uint64_t including_height) { - clean_map_from_items_above(m_last_20_blocks, height); - clean_map_from_items_above(m_last_144_blocks_every_10, height); - clean_map_from_items_above(m_last_144_blocks_every_100, height); - clean_map_from_items_above(m_last_144_blocks_every_1000, height); - m_local_bc_size = height + 1; + clean_map_from_items_above(m_last_20_blocks, including_height); + clean_map_from_items_above(m_last_144_blocks_every_10, including_height); + clean_map_from_items_above(m_last_144_blocks_every_100, including_height); + clean_map_from_items_above(m_last_144_blocks_every_1000, including_height); + m_local_bc_size = including_height; } \ No newline at end of file diff --git a/src/wallet/wallet_chain_shortener.h b/src/wallet/wallet_chain_shortener.h index 29387c00..2ea61366 100644 --- a/src/wallet/wallet_chain_shortener.h +++ b/src/wallet/wallet_chain_shortener.h @@ -30,7 +30,7 @@ public: void get_short_chain_history(std::list& ids)const; bool lookup_item_around(uint64_t i, std::pair& result)const; void check_if_block_matched(uint64_t i, const crypto::hash& id, bool& block_found, bool& block_matched, bool& full_reset_needed) const; - void detach(uint64_t height); + void detach(uint64_t including_height); void clear(); void set_genesis(const crypto::hash& id); const crypto::hash& get_genesis(); diff --git a/tests/core_tests/chaingen.cpp b/tests/core_tests/chaingen.cpp index 4093e710..2a4171bf 100644 --- a/tests/core_tests/chaingen.cpp +++ b/tests/core_tests/chaingen.cpp @@ -923,6 +923,10 @@ bool test_generator::refresh_test_wallet(const std::vector& ev std::atomic atomic_false = ATOMIC_VAR_INIT(false); bool r = w->refresh(blocks_fetched, received_money, ok, atomic_false); CHECK_AND_ASSERT_MES(r, false, "test wallet refersh failed"); + if (expected_blocks_to_be_fetched != blocks_fetched) + { + std::cout << "dd"; + } CHECK_AND_ASSERT_MES(expected_blocks_to_be_fetched == std::numeric_limits::max() || expected_blocks_to_be_fetched == blocks_fetched, false, "test wallet refresh fetched " << blocks_fetched << ", expected: " << expected_blocks_to_be_fetched); bool has_aliases; diff --git a/tests/core_tests/wallet_test_core_proxy.cpp b/tests/core_tests/wallet_test_core_proxy.cpp index 75dac59e..1b423523 100644 --- a/tests/core_tests/wallet_test_core_proxy.cpp +++ b/tests/core_tests/wallet_test_core_proxy.cpp @@ -56,8 +56,25 @@ bool wallet_test_core_proxy::call_COMMAND_RPC_GET_TX_GLOBAL_OUTPUTS_INDEXES(cons bool wallet_test_core_proxy::call_COMMAND_RPC_GET_BLOCKS_FAST(const currency::COMMAND_RPC_GET_BLOCKS_FAST::request& rqt, currency::COMMAND_RPC_GET_BLOCKS_FAST::response& rsp) { - rsp.current_height = 0; + //might be not best way to do it. + std::unordered_map blocks_map; + for (uint64_t i = 0; i != m_blocks.size(); i++) + { + blocks_map[currency::get_block_hash(m_blocks[i]->b)] = i; + } + rsp.start_height = 0; + //find out where we supposed to start refresh + for (auto id : rqt.block_ids) + { + auto it = blocks_map.find(id); + if (it == blocks_map.end()) + continue; + rsp.start_height = it->second; + break; + } + + rsp.current_height = m_blocks.size(); rsp.status = CORE_RPC_STATUS_OK; if (!m_first_call) { @@ -65,20 +82,21 @@ bool wallet_test_core_proxy::call_COMMAND_RPC_GET_BLOCKS_FAST(const currency::CO return true; // respond with empty blocks on second call to gracefully stop wallet refreshing } m_first_call = false; - for (auto b : m_blocks) + for (size_t i = rsp.start_height; i != m_blocks.size(); i++) { + auto b = m_blocks[i]; currency::block_complete_entry bce = AUTO_VAL_INIT(bce); for (auto tx : b->m_transactions) bce.txs.push_back(tx_to_blob(tx)); bce.block = block_to_blob(b->b); rsp.blocks.push_back(bce); } - rsp.current_height = m_blocks.size() - 1; + rsp.current_height = m_blocks.size(); return true; } bool wallet_test_core_proxy::call_COMMAND_RPC_GET_BLOCKS_DIRECT(const currency::COMMAND_RPC_GET_BLOCKS_DIRECT::request& rqt, currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& rsp) { - currency::COMMAND_RPC_GET_BLOCKS_FAST::request req; + currency::COMMAND_RPC_GET_BLOCKS_FAST::request req = AUTO_VAL_INIT(req); req.block_ids = rqt.block_ids; currency::COMMAND_RPC_GET_BLOCKS_FAST::response res = AUTO_VAL_INIT(res); bool r = this->call_COMMAND_RPC_GET_BLOCKS_FAST(req, res);