From 3b975d899e9d075a8ee8d13fa4c0ede0bdf91c2e Mon Sep 17 00:00:00 2001 From: cryptozoidberg Date: Fri, 24 Apr 2020 19:18:19 +0200 Subject: [PATCH] implemented new items lookup and get_short_chain_history --- .../include/serialization/keyvalue_helpers.h | 10 +- src/rpc/core_rpc_server_commands_defs.h | 30 +++++ src/wallet/wallet2.cpp | 118 ++++++++++++++---- src/wallet/wallet2.h | 5 +- 4 files changed, 136 insertions(+), 27 deletions(-) diff --git a/contrib/epee/include/serialization/keyvalue_helpers.h b/contrib/epee/include/serialization/keyvalue_helpers.h index 9d32d024..0ae911b0 100644 --- a/contrib/epee/include/serialization/keyvalue_helpers.h +++ b/contrib/epee/include/serialization/keyvalue_helpers.h @@ -84,6 +84,12 @@ namespace epee return res; } //------------------------------------------------------------------------------------------------------------------- - - +#pragma pack(push, 1) + template + struct pod_pair + { + first_t first; + second_t second; + }; +#pragma pack(pop) } \ No newline at end of file diff --git a/src/rpc/core_rpc_server_commands_defs.h b/src/rpc/core_rpc_server_commands_defs.h index 2d7130bc..275e917e 100644 --- a/src/rpc/core_rpc_server_commands_defs.h +++ b/src/rpc/core_rpc_server_commands_defs.h @@ -141,6 +141,36 @@ namespace currency typedef COMMAND_RPC_GET_BLOCKS_FAST_T COMMAND_RPC_GET_BLOCKS_FAST; typedef COMMAND_RPC_GET_BLOCKS_FAST_T COMMAND_RPC_GET_BLOCKS_DIRECT; + template + struct COMMAND_RPC_GET_BLOCKS_FUZZY_FAST_T + { + + 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 */ + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE_CONTAINER_POD_AS_BLOB(block_ids) + END_KV_SERIALIZE_MAP() + }; + + struct response + { + std::list blocks; + uint64_t start_height; + uint64_t current_height; + std::string status; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(blocks) + KV_SERIALIZE(start_height) + KV_SERIALIZE(current_height) + KV_SERIALIZE(status) + END_KV_SERIALIZE_MAP() + }; + }; + typedef COMMAND_RPC_GET_BLOCKS_FUZZY_FAST_T COMMAND_RPC_GET_BLOCKS_FUZZY_FAST; + typedef COMMAND_RPC_GET_BLOCKS_FUZZY_FAST_T COMMAND_RPC_GET_BLOCKS_FUZZY_DIRECT; //----------------------------------------------- diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index a418be65..728e3011 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1149,39 +1149,111 @@ void wallet2::push_new_block_id(const crypto::hash& id, uint64_t height) } //---------------------------------------------------------------------------------------------------- -void wallet2::get_short_chain_history(std::list& ids) +// void wallet2::get_short_chain_history(std::list& ids) +// { +// ids.clear(); +// size_t i = 0; +// size_t current_multiplier = 1; +// size_t sz = get_blockchain_current_height(); +// if(!sz) +// return; +// size_t current_back_offset = 1; +// bool genesis_included = false; +// while(current_back_offset < sz) +// { +// ids.push_back(m_blockchain[sz-current_back_offset]); +// if(sz-current_back_offset == 0) +// genesis_included = true; +// if(i < 10) +// { +// ++current_back_offset; +// }else +// { +// current_back_offset += current_multiplier *= 2; +// } +// ++i; +// } +// if(!genesis_included) +// ids.push_back(m_blockchain[0]); +// } +//---------------------------------------------------------------------------------------------------- +bool wallet2::lookup_item_around(uint64_t i, std::pair& result) +{ + //in which container we are looking for? + uint64_t devider = 0; + std::map* pcontainer; + if (m_last_144_blocks_every_10.size() && i < m_last_144_blocks_every_10.begin()->first) + { + devider = 10; + pcontainer = &m_last_144_blocks_every_10; + } + else if (m_last_144_blocks_every_100.size() && i < m_last_144_blocks_every_100.begin()->first) + { + devider = 100; + pcontainer = &m_last_144_blocks_every_100; + } + else if (m_last_144_blocks_every_1000.size() && i < m_last_144_blocks_every_1000.begin()->first) + { + devider = 1000; + pcontainer = &m_last_144_blocks_every_1000; + } + else + return false; + + //look in every 10'th + i = i - i % devider; + auto it = pcontainer->find(i); + //self check + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it != pcontainer->end(), + "Inernal error: amount " << i << " not found for devider " << devider + << " pcontainer={" << pcontainer->begin()->first << ":"<< (--pcontainer->end())->first <<"}"); + result = *it; + return true; +} +//---------------------------------------------------------------------------------------------------- +void wallet2::get_short_chain_history(std::list >& ids) { ids.clear(); - size_t i = 0; - size_t current_multiplier = 1; - size_t sz = get_blockchain_current_height(); - if(!sz) + uint64_t i = 0; + uint64_t sz = get_blockchain_current_height(); + if (!sz) return; - size_t current_back_offset = 1; - bool genesis_included = false; - while(current_back_offset < sz) + + //first put last 10 + for (auto it = m_last_10_blocks.rbegin(); it != m_last_10_blocks.rend(); it++) { - ids.push_back(m_blockchain[sz-current_back_offset]); - if(sz-current_back_offset == 0) - genesis_included = true; - if(i < 10) - { - ++current_back_offset; - }else - { - current_back_offset += current_multiplier *= 2; - } - ++i; + ids.push_back({ it->first, it->second }); + i = it->first; } - if(!genesis_included) - ids.push_back(m_blockchain[0]); + + uint64_t current_back_offset = m_last_10_blocks.size(); + //self check + WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(current_back_offset == sz-i, "Inernal error: current_back_offset{" << current_back_offset << "} == sz-i{" << sz << " - " << i << "} is not equal"); + + uint64_t current_offset_distance = 10; + current_back_offset += 10; + while (current_back_offset < sz) + { + uint64_t get_item_around = sz - current_back_offset; + std::pair item = AUTO_VAL_INIT(item); + if (!lookup_item_around(get_item_around, item)) + break; + + //readjust item current_back_offset + current_back_offset = sz - item.first; + + ids.push_back(item); + current_offset_distance *= 2; + current_back_offset += current_offset_distance; + } + ids.push_back({ 0, m_genesis }); } //---------------------------------------------------------------------------------------------------- void wallet2::pull_blocks(size_t& blocks_added, std::atomic& stop) { blocks_added = 0; - currency::COMMAND_RPC_GET_BLOCKS_DIRECT::request req = AUTO_VAL_INIT(req); - currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response res = AUTO_VAL_INIT(res); + currency::COMMAND_RPC_GET_BLOCKS_FUZZY_DIRECT::request req = AUTO_VAL_INIT(req); + currency::COMMAND_RPC_GET_BLOCKS_FUZZY_DIRECT::response res = AUTO_VAL_INIT(res); get_short_chain_history(req.block_ids); bool r = m_core_proxy->call_COMMAND_RPC_GET_BLOCKS_DIRECT(req, res); if (!r) diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 00ff344a..f01a12cb 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -638,7 +638,7 @@ 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); - uint64_t get_blockchain_current_height() const { + inline uint64_t get_blockchain_current_height() const { return m_last_10_blocks.empty() ? 0 : (--m_last_10_blocks.end())->first + 1; } @@ -778,7 +778,6 @@ private: 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 get_short_chain_history(std::list& ids); bool extract_offers_from_transfer_entry(size_t i, std::unordered_map& offers_local); bool select_my_offers(std::list& offers); bool clear(); @@ -892,6 +891,8 @@ private: bool store_unsigned_tx_to_file_and_reserve_transfers(const finalize_tx_param& ftp, const std::string& filename, std::string* p_unsigned_tx_blob_str = nullptr); void check_and_throw_if_self_directed_tx_with_payment_id_requested(const construct_tx_param& ctp); void push_new_block_id(const crypto::hash& id, uint64_t height); + bool lookup_item_around(uint64_t i, std::pair& result); + void get_short_chain_history(std::list >& ids); currency::account_base m_account; bool m_watch_only;