From caaca44f1e0d39cf7a1203f6826fd94bdf038b96 Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Sat, 25 Apr 2020 00:30:55 +0200 Subject: [PATCH] re-implemented detach blocks --- src/rpc/core_rpc_server_commands_defs.h | 2 +- src/simplewallet/simplewallet.cpp | 2 +- src/wallet/wallet2.cpp | 68 ++++++++++++++++--------- src/wallet/wallet2.h | 12 +++-- 4 files changed, 52 insertions(+), 32 deletions(-) diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 275e917e..725f5860 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -147,7 +147,7 @@ namespace currency struct request { - std::list > block_ids; //*first 10 blocks id goes sequential, next goes in pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */ + std::list > block_ids; //*first 10 blocks id goes sequential, next goes in pow(2,n) offset, like 2, 4, 8, 16, 32, 64 and so on, and the last one is always genesis block */ BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE_CONTAINER_POD_AS_BLOB(block_ids) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 36d23a7f..c1978d57 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1116,7 +1116,7 @@ bool simple_wallet::show_blockchain_height(const std::vector& args) bool simple_wallet::show_wallet_bcheight(const std::vector& args) { - uint64_t bc_height = m_wallet->get_blockchain_current_height(); + uint64_t bc_height = m_wallet->get_blockchain_current_size(); success_msg_writer() << bc_height; return true; } diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 76e62404..2f596686 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1070,8 +1070,8 @@ void wallet2::process_unconfirmed(const currency::transaction& tx, std::vector& stop) return; } THROW_IF_TRUE_WALLET_EX(res.status != CORE_RPC_STATUS_OK, error::get_blocks_error, res.status); - THROW_IF_TRUE_WALLET_EX(get_blockchain_current_height() && get_blockchain_current_height() <= res.start_height, error::wallet_internal_error, + THROW_IF_TRUE_WALLET_EX(get_blockchain_current_size() && get_blockchain_current_size() <= res.start_height, error::wallet_internal_error, "wrong daemon response: m_start_height=" + std::to_string(res.start_height) + - " not less than local blockchain size=" + std::to_string(get_blockchain_current_height())); + " not less than local blockchain size=" + std::to_string(get_blockchain_current_size())); handle_pulled_blocks(blocks_added, stop, res); } @@ -1357,7 +1357,7 @@ void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic& stop { size_t current_index = res.start_height; - if (res.start_height == 0 && get_blockchain_current_height() == 1 && !res.blocks.empty()) + if (res.start_height == 0 && get_blockchain_current_size() == 1 && !res.blocks.empty()) { const currency::block& genesis = res.blocks.front().block_ptr->bl; THROW_IF_TRUE_WALLET_EX(get_block_height(genesis) != 0, error::wallet_internal_error, "first block expected to be genesis"); @@ -1375,7 +1375,7 @@ void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic& stop const currency::block& bl = bl_entry.block_ptr->bl; uint64_t height = get_block_height(bl); - uint64_t processed_blocks_count = get_blockchain_current_height(); + uint64_t processed_blocks_count = get_blockchain_current_size(); //TODO: get_block_hash is slow crypto::hash bl_id = get_block_hash(bl); @@ -1422,7 +1422,7 @@ void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic& stop WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(been_matched_block, "unmatched block while never been mathced block"); } - + //TODO: take into account date of wallet creation //reorganize detach_blockchain(last_matched_index); process_new_blockchain_entry(bl, bl_entry, bl_id, height); @@ -1443,7 +1443,7 @@ void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic& stop } } - WLT_LOG_L1("[PULL BLOCKS] " << res.start_height << " --> " << get_blockchain_current_height()); + WLT_LOG_L1("[PULL BLOCKS] " << res.start_height << " --> " << get_blockchain_current_size()); } //---------------------------------------------------------------------------------------------------- uint64_t wallet2::get_sync_progress() @@ -1820,7 +1820,7 @@ void wallet2::refresh(size_t & blocks_fetched, bool& received_money, std::atomic size_t added_blocks = 0; size_t try_count = 0; crypto::hash last_tx_hash_id = m_transfers.size() ? get_transaction_hash(m_transfers.back().m_ptx_wallet_info->m_tx) : null_hash; - m_height_of_start_sync = get_blockchain_current_height(); + m_height_of_start_sync = get_blockchain_current_size(); m_last_sync_percent = 0; while (!stop.load(std::memory_order_relaxed)) { @@ -1929,6 +1929,26 @@ bool wallet2::refresh(size_t & blocks_fetched, bool& received_money, bool& ok, s return ok; } //---------------------------------------------------------------------------------------------------- +void clean_map_from_items_above(std::map& container, uint64_t height) +{ + while (container.size() && (--container.end())->first > height) + { + container.erase(--container.end()); + } +} +//---------------------------------------------------------------------------------------------------- +uint64_t wallet2::detach_from_block_ids(uint64_t height) +{ + //calculate number of erased blocks + uint64_t blocks_detached = (get_blockchain_current_size() -1 ) - height; + //id at height should be kept, the rest - erased + clean_map_from_items_above(m_last_10_blocks, height); + clean_map_from_items_above(m_last_10_blocks, height); + clean_map_from_items_above(m_last_10_blocks, height); + clean_map_from_items_above(m_last_10_blocks, height); + return blocks_detached; +} +//---------------------------------------------------------------------------------------------------- void wallet2::detach_blockchain(uint64_t height) { WLT_LOG_L0("Detaching blockchain on height " << height); @@ -1953,9 +1973,8 @@ void wallet2::detach_blockchain(uint64_t height) } } - size_t blocks_detached = m_blockchain.end() - (m_blockchain.begin()+height); - m_blockchain.erase(m_blockchain.begin()+height, m_blockchain.end()); - m_local_bc_height -= blocks_detached; + size_t blocks_detached = detach_from_block_ids(height); + m_local_bc_size -= height+1; //rollback spends // do not clear spent flag in spent transfers as corresponding txs are most likely in the pool @@ -2043,7 +2062,7 @@ bool wallet2::reset_all() m_transfer_history.clear(); //m_account = AUTO_VAL_INIT(m_account); - m_local_bc_height = 1; + m_local_bc_size = 1; //including genesis m_last_bc_timestamp = 0; m_height_of_start_sync = 0; m_last_sync_percent = 0; @@ -2285,7 +2304,6 @@ void wallet2::load(const std::wstring& wallet_, const std::string& password) { reset_history(); } - m_local_bc_height = get_blockchain_current_height(); THROW_IF_TRUE_WALLET_EX(need_to_resync, error::wallet_load_notice_wallet_restored, epee::string_encoding::convert_to_ansii(m_wallet_file)); WLT_LOG_L0("Loaded wallet file" << (m_watch_only ? " (WATCH ONLY) " : " ") << string_encoding::convert_to_ansii(m_wallet_file) << " with public address: " << m_account.get_public_address_str()); @@ -2833,7 +2851,7 @@ bool wallet2::is_transfer_okay_for_pos(const transfer_details& tr, uint64_t& sta return false; //prevent staking of after-last-pow-coins - if (get_blockchain_current_height() - tr.m_ptx_wallet_info->m_block_height <= m_core_runtime_config.min_coinstake_age) + if (get_blockchain_current_size() - tr.m_ptx_wallet_info->m_block_height <= m_core_runtime_config.min_coinstake_age) return false; if (tr.m_ptx_wallet_info->m_block_height > m_last_pow_block_h) @@ -3155,20 +3173,20 @@ bool wallet2::is_transfer_unlocked(const transfer_details& td, bool for_pos_mini if (td.m_flags&WALLET_TRANSFER_DETAIL_FLAG_BLOCKED) return false; - if (td.m_ptx_wallet_info->m_block_height + WALLET_DEFAULT_TX_SPENDABLE_AGE > get_blockchain_current_height()) + if (td.m_ptx_wallet_info->m_block_height + WALLET_DEFAULT_TX_SPENDABLE_AGE > get_blockchain_current_size()) return false; uint64_t unlock_time = get_tx_unlock_time(td.m_ptx_wallet_info->m_tx, td.m_internal_output_index); - if (for_pos_mining && get_blockchain_current_height() > m_core_runtime_config.hard_fork1_starts_after_height) + if (for_pos_mining && get_blockchain_current_size() > m_core_runtime_config.hard_fork1_starts_after_height) { //allowed of staking locked coins with stake_lock_time = unlock_time; } else { - if (!currency::is_tx_spendtime_unlocked(unlock_time, get_blockchain_current_height(), m_core_runtime_config.get_core_time())) + if (!currency::is_tx_spendtime_unlocked(unlock_time, get_blockchain_current_size(), m_core_runtime_config.get_core_time())) return false; } return true; @@ -4257,16 +4275,16 @@ void wallet2::process_genesis_if_needed(const currency::block& genesis) if (!m_transfers.empty() || !m_key_images.empty()) return; - THROW_IF_TRUE_WALLET_EX(get_blockchain_current_height() > 1, error::wallet_internal_error, "Can't change wallet genesis block once the blockchain has been populated"); + THROW_IF_TRUE_WALLET_EX(get_blockchain_current_size() > 1, error::wallet_internal_error, "Can't change wallet genesis block once the blockchain has been populated"); crypto::hash genesis_hash = get_block_hash(genesis); - if (get_blockchain_current_height() == 1 && m_blockchain[0] != genesis_hash) + if (get_blockchain_current_size() == 1 && m_blockchain[0] != genesis_hash) WLT_LOG_L0("Changing genesis block for wallet " << m_account.get_public_address_str() << ":" << ENDL << " " << m_blockchain[0] << " -> " << genesis_hash); m_blockchain.clear(); m_blockchain.push_back(genesis_hash); - m_local_bc_height = 1; + m_local_bc_size = 1; m_last_bc_timestamp = genesis.timestamp; WLT_LOG_L2("Processing genesis block: " << genesis_hash); @@ -4275,7 +4293,7 @@ void wallet2::process_genesis_if_needed(const currency::block& genesis) void wallet2::set_genesis(const crypto::hash& genesis_hash) { - THROW_IF_TRUE_WALLET_EX(get_blockchain_current_height() != 1, error::wallet_internal_error, "Can't change wallet genesis hash once the blockchain has been populated"); + THROW_IF_TRUE_WALLET_EX(get_blockchain_current_size() != 1, error::wallet_internal_error, "Can't change wallet genesis hash once the blockchain has been populated"); WLT_LOG_L0("Changing genesis hash for wallet " << m_account.get_public_address_str() << ":" << ENDL << " " << m_blockchain[0] << " -> " << genesis_hash); m_blockchain[0] = genesis_hash; } diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 11a3a0ff..d0d71597 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -638,8 +638,8 @@ namespace tools uint64_t fee, size_t& outs_total, uint64_t& amount_total, size_t& outs_swept, currency::transaction* p_result_tx = nullptr, std::string* p_filename_or_unsigned_tx_blob_str = nullptr); bool get_transfer_address(const std::string& adr_str, currency::account_public_address& addr, std::string& payment_id); - inline uint64_t get_blockchain_current_height() const { - return m_last_10_blocks.empty() ? 0 : (--m_last_10_blocks.end())->first + 1; + inline uint64_t get_blockchain_current_size() const { + return m_local_bc_size; } template @@ -676,10 +676,11 @@ namespace tools //convert from old version if (ver < CURRENCY_FORMATION_VERSION + 65) { - //TODO: a & m_blockchain; + //TODO: export from a & m_blockchain; } else { + a & m_local_bc_size; a & m_genesis; a & m_last_10_blocks; a & m_last_144_blocks_every_10; @@ -715,7 +716,7 @@ namespace tools //for unit tests friend class ::test_generator; - //next functions in public area only because of test_generator + //next functions in public area only becausce of test_generator //TODO: Need refactoring - remove it back to private zone void set_genesis(const crypto::hash& genesis_hash); bool prepare_and_sign_pos_block(currency::block& b, @@ -894,6 +895,7 @@ private: bool lookup_item_around(uint64_t i, std::pair& result); void get_short_chain_history(std::list >& ids); void check_if_block_matched(uint64_t i, const crypto::hash& id, bool& block_found, bool& block_matched, bool& full_reset_needed); + uint64_t detach_from_block_ids(uint64_t height); currency::account_base m_account; bool m_watch_only; @@ -908,7 +910,7 @@ private: std::map m_last_144_blocks_every_100; //10 days std::map m_last_144_blocks_every_1000; //100 days - std::atomic m_local_bc_height; //temporary workaround + std::atomic m_local_bc_size; //temporary workaround std::atomic m_last_bc_timestamp; bool m_do_rise_transfer; uint64_t m_pos_mint_packing_size;