forked from lthn/blockchain
moved shortener code into separate unit to create unit tests for it
This commit is contained in:
parent
e5f3519c1e
commit
281e430317
7 changed files with 320 additions and 220 deletions
|
|
@ -39,7 +39,6 @@ namespace currency
|
|||
bool init(const boost::program_options::variables_map& vm);
|
||||
|
||||
bool on_get_blocks_direct(const COMMAND_RPC_GET_BLOCKS_DIRECT::request& req, COMMAND_RPC_GET_BLOCKS_DIRECT::response& res, connection_context& cntx);
|
||||
bool on_get_blocks_fuzzy_direct(const COMMAND_RPC_GET_BLOCKS_FUZZY_DIRECT::request& req, COMMAND_RPC_GET_BLOCKS_FUZZY_DIRECT::response& res, connection_context& cntx);
|
||||
|
||||
|
||||
bool on_get_height(const COMMAND_RPC_GET_HEIGHT::request& req, COMMAND_RPC_GET_HEIGHT::response& res, connection_context& cntx);
|
||||
|
|
|
|||
|
|
@ -1100,54 +1100,7 @@ void wallet2::process_new_blockchain_entry(const currency::block& b, const curre
|
|||
m_wcallback->on_new_block(height, b);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::push_new_block_id(const crypto::hash& id, uint64_t height)
|
||||
{
|
||||
//primary 10
|
||||
//self check
|
||||
if (!m_last_10_blocks.empty())
|
||||
{
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(get_blockchain_current_size() == height, "Inernal error: get_blockchain_current_height(){" << get_blockchain_current_size() << "} == height{" << height << "} is not equal");
|
||||
}
|
||||
|
||||
m_last_10_blocks[height] = id;
|
||||
if (m_last_10_blocks.size() > WALLET_EVERYBLOCK_SIZE)
|
||||
{
|
||||
m_last_10_blocks.erase(m_last_10_blocks.begin());
|
||||
}
|
||||
|
||||
//every 10-th
|
||||
if (height % 10 == 0)
|
||||
{
|
||||
//self check
|
||||
if (!m_last_144_blocks_every_10.empty())
|
||||
{
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX((--m_last_144_blocks_every_10.end())->first + 10 == height, "Inernal error: (--m_last_144_blocks_every_10.end())->first + 10{" << (--m_last_144_blocks_every_10.end())->first + 10 << "} == height{" << height << "} is not equal");
|
||||
}
|
||||
m_last_144_blocks_every_10[height] = id;
|
||||
}
|
||||
//every 100-th
|
||||
if (height % 100 == 0)
|
||||
{
|
||||
//self check
|
||||
if (!m_last_144_blocks_every_100.empty())
|
||||
{
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX((--m_last_144_blocks_every_100.end())->first + 100 == height, "Inernal error: (--m_last_144_blocks_every_100.end())->first + 100{" << (--m_last_144_blocks_every_100.end())->first + 100 << "} == height{" << height << "} is not equal");
|
||||
}
|
||||
m_last_144_blocks_every_100[height] = id;
|
||||
}
|
||||
//every 1000-th
|
||||
//every 100-th
|
||||
if (height % 1000 == 0)
|
||||
{
|
||||
//self check
|
||||
if (!m_last_144_blocks_every_1000.empty())
|
||||
{
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX((--m_last_144_blocks_every_1000.end())->first + 1000 == height, "Inernal error: (--m_last_144_blocks_every_1000.end())->first + 1000{" << (--m_last_144_blocks_every_1000.end())->first + 1000 << "} == height{" << height << "} is not equal");
|
||||
}
|
||||
m_last_144_blocks_every_1000[height] = id;
|
||||
}
|
||||
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
// void wallet2::get_short_chain_history(std::list<crypto::hash>& ids)
|
||||
// {
|
||||
|
|
@ -1176,78 +1129,7 @@ void wallet2::push_new_block_id(const crypto::hash& id, uint64_t height)
|
|||
// if(!genesis_included)
|
||||
// ids.push_back(m_blockchain[0]);
|
||||
// }
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet2::lookup_item_around(uint64_t i, std::pair<uint64_t, crypto::hash>& result)
|
||||
{
|
||||
//in which container we are looking for?
|
||||
uint64_t devider = 0;
|
||||
std::map<uint64_t, crypto::hash>* 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: index " << 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<crypto::hash>& ids)
|
||||
{
|
||||
ids.clear();
|
||||
uint64_t i = 0;
|
||||
uint64_t sz = get_blockchain_current_size();
|
||||
if (!sz)
|
||||
return;
|
||||
|
||||
//first put last 10
|
||||
for (auto it = m_last_10_blocks.rbegin(); it != m_last_10_blocks.rend(); it++)
|
||||
{
|
||||
ids.push_back(it->second);
|
||||
i = it->first;
|
||||
}
|
||||
|
||||
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<uint64_t, crypto::hash> 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.second);
|
||||
current_offset_distance *= 2;
|
||||
current_back_offset += current_offset_distance;
|
||||
}
|
||||
ids.push_back(m_genesis);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::set_minimum_height(uint64_t h)
|
||||
{
|
||||
|
|
@ -1264,7 +1146,7 @@ uint64_t wallet2::get_wallet_minimum_height()
|
|||
req.timestamp = m_account.get_createtime();
|
||||
bool r = m_core_proxy->call_COMMAND_RPC_GET_EST_HEIGHT_FROM_DATE(req, res);
|
||||
THROW_IF_FALSE_WALLET_EX(r, error::no_connection_to_daemon, "call_COMMAND_RPC_GET_EST_HEIGHT_FROM_DATE");
|
||||
THROW_IF_FALSE_WALLET_EX(res.status == CORE_RPC_STATUS_OK, error::wallet_runtime_error, "FAILED TO CALL COMMAND_RPC_GET_EST_HEIGHT_FROM_DATE");
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(res.status == CORE_RPC_STATUS_OK, "FAILED TO CALL COMMAND_RPC_GET_EST_HEIGHT_FROM_DATE");
|
||||
return res.h;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
@ -1300,7 +1182,7 @@ void wallet2::pull_blocks(size_t& blocks_added, std::atomic<bool>& stop)
|
|||
WLT_LOG_MAGENTA("New genesis set for wallet: " << new_genesis_id, LOG_LEVEL_0);
|
||||
get_short_chain_history(req.block_ids);
|
||||
//req.block_ids.push_back(new_genesis_id);
|
||||
bool r = m_core_proxy->call_COMMAND_RPC_GET_BLOCKS_FUZZY_DIRECT(req, res);
|
||||
bool r = m_core_proxy->call_COMMAND_RPC_GET_BLOCKS_DIRECT(req, res);
|
||||
THROW_IF_TRUE_WALLET_EX(!r, error::no_connection_to_daemon, "getblocks.bin");
|
||||
}
|
||||
if (res.status == CORE_RPC_STATUS_BUSY)
|
||||
|
|
@ -1316,62 +1198,7 @@ void wallet2::pull_blocks(size_t& blocks_added, std::atomic<bool>& stop)
|
|||
|
||||
handle_pulled_blocks(blocks_added, stop, res);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::check_if_block_matched(uint64_t i, const crypto::hash& id, bool& block_found, bool& block_matched, bool& full_reset_needed)
|
||||
{
|
||||
if (!m_last_10_blocks.empty() && i > m_last_10_blocks.begin()->first)
|
||||
{
|
||||
//must be in short sequence (m_last_10_blocks)
|
||||
//self check
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX((--m_last_10_blocks.end())->first >= i,
|
||||
"Inernal error: index " << i << " is not located in expected range of m_last_10_blocks={"
|
||||
<< m_last_10_blocks.begin()->first << ":" << (--m_last_10_blocks.end())->first << "}");
|
||||
|
||||
auto it = m_last_10_blocks.find(i);
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it != m_last_10_blocks.end(),
|
||||
"Inernal error: filde to find index " << i << " in m_last_10_blocks={"
|
||||
<< m_last_10_blocks.begin()->first << ":" << (--m_last_10_blocks.end())->first << "}");
|
||||
|
||||
block_found = true;
|
||||
if (id == it->second)
|
||||
block_matched = true;
|
||||
else
|
||||
block_matched = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//lazy lookup
|
||||
std::pair<uint64_t, crypto::hash> result = AUTO_VAL_INIT(result);
|
||||
bool r = lookup_item_around(i, result);
|
||||
if (!r)
|
||||
{
|
||||
WLT_LOG_L0("Wallet is getting fully resynced due to unmatched block " << id << " at " << i );
|
||||
block_matched = block_found = false;
|
||||
full_reset_needed = true;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (result.first == i)
|
||||
{
|
||||
block_found = true;
|
||||
if (result.second == id)
|
||||
{
|
||||
block_matched = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
block_matched = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
block_found = false;
|
||||
block_matched = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet2::handle_pulled_blocks(size_t& blocks_added, std::atomic<bool>& stop,
|
||||
currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& res)
|
||||
|
|
@ -1949,24 +1776,14 @@ bool wallet2::refresh(size_t & blocks_fetched, bool& received_money, bool& ok, s
|
|||
}
|
||||
return ok;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void clean_map_from_items_above(std::map<uint64_t, crypto::hash>& 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);
|
||||
m_chain.detach(height);
|
||||
return blocks_detached;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
|
|
@ -2064,11 +1881,7 @@ bool wallet2::clear()
|
|||
reset_all();
|
||||
//currency::block b;
|
||||
//currency::generate_genesis_block(b);
|
||||
m_local_bc_size = 1;
|
||||
m_last_10_blocks.clear();
|
||||
m_last_144_blocks_every_10.clear();
|
||||
m_last_144_blocks_every_100.clear();
|
||||
m_last_144_blocks_every_1000.clear();
|
||||
m_chain.clear();
|
||||
//m_blockchain.push_back(get_block_hash(b));
|
||||
return true;
|
||||
}
|
||||
|
|
@ -2076,10 +1889,7 @@ bool wallet2::clear()
|
|||
bool wallet2::reset_all()
|
||||
{
|
||||
//m_blockchain.clear();
|
||||
m_last_10_blocks.clear();
|
||||
m_last_144_blocks_every_10.clear();
|
||||
m_last_144_blocks_every_100.clear();
|
||||
m_last_144_blocks_every_1000.clear();
|
||||
m_chain.clear();
|
||||
m_transfers.clear();
|
||||
m_key_images.clear();
|
||||
// m_pending_key_images is not cleared intentionally
|
||||
|
|
@ -2092,7 +1902,7 @@ bool wallet2::reset_all()
|
|||
m_transfer_history.clear();
|
||||
//m_account = AUTO_VAL_INIT(m_account);
|
||||
|
||||
m_local_bc_size = 1; //including genesis
|
||||
//m_local_bc_size = 1; //including genesis
|
||||
m_last_bc_timestamp = 0;
|
||||
m_height_of_start_sync = 0;
|
||||
m_last_sync_percent = 0;
|
||||
|
|
@ -3207,7 +3017,7 @@ bool wallet2::is_transfer_unlocked(const transfer_details& td, bool for_pos_mini
|
|||
|
||||
|
||||
uint64_t unlock_time = get_tx_unlock_time(td.m_ptx_wallet_info->m_tx, td.m_internal_output_index);
|
||||
if (for_pos_mining && m_blockchain.size() > m_core_runtime_config.hard_fork_01_starts_after_height)
|
||||
if (for_pos_mining && get_blockchain_current_size() > m_core_runtime_config.hard_fork_01_starts_after_height)
|
||||
{
|
||||
//allowed of staking locked coins with
|
||||
stake_lock_time = unlock_time;
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@
|
|||
#include "currency_core/bc_offers_serialization.h"
|
||||
#include "currency_core/bc_escrow_service.h"
|
||||
#include "common/pod_array_file_container.h"
|
||||
#include "wallet_chain_shortener.h"
|
||||
|
||||
|
||||
#define WALLET_DEFAULT_TX_SPENDABLE_AGE 10
|
||||
|
|
@ -46,11 +47,6 @@
|
|||
|
||||
#define WALLET_DEFAULT_POS_MINT_PACKING_SIZE 100
|
||||
|
||||
#define WALLET_EVERYBLOCK_SIZE 10
|
||||
#define WALLET_EVERY_10_BLOCKS_SIZE 144
|
||||
#define WALLET_EVERY_100_BLOCKS_SIZE 144
|
||||
#define WALLET_EVERY_1000_BLOCKS_SIZE 144
|
||||
|
||||
|
||||
#undef LOG_DEFAULT_CHANNEL
|
||||
#define LOG_DEFAULT_CHANNEL "wallet"
|
||||
|
|
@ -644,10 +640,10 @@ namespace tools
|
|||
|
||||
bool get_transfer_address(const std::string& adr_str, currency::account_public_address& addr, std::string& payment_id);
|
||||
inline uint64_t get_blockchain_current_size() const {
|
||||
return m_local_bc_size;
|
||||
return m_chain.get_blockchain_current_size();
|
||||
}
|
||||
|
||||
uint64_t get_top_block_height() const { return m_blockchain.empty() ? 0 : m_blockchain.size() - 1; }
|
||||
uint64_t get_top_block_height() const { return m_chain.get_top_block_height(); }
|
||||
|
||||
template <class t_archive>
|
||||
inline void serialize(t_archive &a, const unsigned int ver)
|
||||
|
|
@ -687,12 +683,13 @@ namespace tools
|
|||
}
|
||||
else
|
||||
{
|
||||
a & m_local_bc_size;
|
||||
a & m_genesis;
|
||||
a & m_last_10_blocks;
|
||||
a & m_last_144_blocks_every_10;
|
||||
a & m_last_144_blocks_every_100;
|
||||
a & m_last_144_blocks_every_1000;
|
||||
a & m_chain;
|
||||
// a & m_local_bc_size;
|
||||
// a & m_genesis;
|
||||
// a & m_last_10_blocks;
|
||||
// a & m_last_144_blocks_every_10;
|
||||
// a & m_last_144_blocks_every_100;
|
||||
// a & m_last_144_blocks_every_1000;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -825,7 +822,7 @@ private:
|
|||
const std::vector<std::string>& recipients,
|
||||
const std::vector<std::string>& recipients_aliases);
|
||||
void handle_pulled_blocks(size_t& blocks_added, std::atomic<bool>& stop,
|
||||
currency::COMMAND_RPC_GET_BLOCKS_FUZZY_DIRECT::response& blocks);
|
||||
currency::COMMAND_RPC_GET_BLOCKS_DIRECT::response& blocks);
|
||||
std::string get_alias_for_address(const std::string& addr);
|
||||
static bool build_kernel(const currency::pos_entry& pe, const currency::stake_modifier_type& stake_modifier, currency::stake_kernel& kernel, uint64_t& coindays_weight, uint64_t timestamp);
|
||||
bool is_connected_to_net();
|
||||
|
|
@ -915,14 +912,14 @@ private:
|
|||
std::wstring m_pending_ki_file;
|
||||
std::string m_password;
|
||||
//std::vector<crypto::hash> m_blockchain;
|
||||
crypto::hash m_genesis;
|
||||
std::map<uint64_t, crypto::hash> m_last_10_blocks;
|
||||
std::map<uint64_t, crypto::hash> m_last_144_blocks_every_10; //1 day
|
||||
std::map<uint64_t, crypto::hash> m_last_144_blocks_every_100; //10 days
|
||||
std::map<uint64_t, crypto::hash> m_last_144_blocks_every_1000; //100 days
|
||||
// crypto::hash m_genesis;
|
||||
// std::map<uint64_t, crypto::hash> m_last_10_blocks;
|
||||
// std::map<uint64_t, crypto::hash> m_last_144_blocks_every_10; //1 day
|
||||
// std::map<uint64_t, crypto::hash> m_last_144_blocks_every_100; //10 days
|
||||
// std::map<uint64_t, crypto::hash> m_last_144_blocks_every_1000; //100 days
|
||||
uint64_t m_minimum_height;
|
||||
|
||||
std::atomic<uint64_t> m_local_bc_size; //temporary workaround
|
||||
//std::atomic<uint64_t> m_local_bc_size; //temporary workaround
|
||||
std::atomic<uint64_t> m_last_bc_timestamp;
|
||||
bool m_do_rise_transfer;
|
||||
uint64_t m_pos_mint_packing_size;
|
||||
|
|
@ -949,6 +946,7 @@ private:
|
|||
uint64_t m_last_pow_block_h;
|
||||
currency::core_runtime_config m_core_runtime_config;
|
||||
escrow_contracts_container m_contracts;
|
||||
wallet_chain_shortener m_chain;
|
||||
std::list<expiration_entry_info> m_money_expirations;
|
||||
//optimization for big wallets and batch tx
|
||||
|
||||
|
|
|
|||
225
src/wallet/wallet_chain_shortener.cpp
Normal file
225
src/wallet/wallet_chain_shortener.cpp
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
// Copyright (c) 2014-2019 Zano Project
|
||||
// Copyright (c) 2014-2018 The Louisdor Project
|
||||
// Copyright (c) 2012-2013 The Cryptonote developers
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include "wallet_chain_shortener.h"
|
||||
|
||||
#define WALLET_EVERYBLOCK_SIZE 10
|
||||
#define WALLET_EVERY_10_BLOCKS_SIZE 144
|
||||
#define WALLET_EVERY_100_BLOCKS_SIZE 144
|
||||
#define WALLET_EVERY_1000_BLOCKS_SIZE 144
|
||||
|
||||
|
||||
|
||||
void wallet_chain_shortener::clear()
|
||||
{
|
||||
m_local_bc_size = 1;
|
||||
m_last_10_blocks.clear();
|
||||
m_last_144_blocks_every_10.clear();
|
||||
m_last_144_blocks_every_100.clear();
|
||||
m_last_144_blocks_every_1000.clear();
|
||||
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet_chain_shortener::get_blockchain_current_size() const
|
||||
{
|
||||
return m_local_bc_size;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
uint64_t wallet_chain_shortener::get_top_block_height() const
|
||||
{
|
||||
return m_local_bc_size - 1;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet_chain_shortener::push_new_block_id(const crypto::hash& id, uint64_t height)
|
||||
{
|
||||
//primary 10
|
||||
//self check
|
||||
if (!m_last_10_blocks.empty())
|
||||
{
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(get_blockchain_current_size() == height, "Inernal error: get_blockchain_current_height(){" << get_blockchain_current_size() << "} == height{" << height << "} is not equal");
|
||||
}
|
||||
|
||||
m_last_10_blocks[height] = id;
|
||||
if (m_last_10_blocks.size() > WALLET_EVERYBLOCK_SIZE)
|
||||
{
|
||||
m_last_10_blocks.erase(m_last_10_blocks.begin());
|
||||
}
|
||||
|
||||
//every 10-th
|
||||
if (height % 10 == 0)
|
||||
{
|
||||
//self check
|
||||
if (!m_last_144_blocks_every_10.empty())
|
||||
{
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX((--m_last_144_blocks_every_10.end())->first + 10 == height, "Inernal error: (--m_last_144_blocks_every_10.end())->first + 10{" << (--m_last_144_blocks_every_10.end())->first + 10 << "} == height{" << height << "} is not equal");
|
||||
}
|
||||
m_last_144_blocks_every_10[height] = id;
|
||||
}
|
||||
//every 100-th
|
||||
if (height % 100 == 0)
|
||||
{
|
||||
//self check
|
||||
if (!m_last_144_blocks_every_100.empty())
|
||||
{
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX((--m_last_144_blocks_every_100.end())->first + 100 == height, "Inernal error: (--m_last_144_blocks_every_100.end())->first + 100{" << (--m_last_144_blocks_every_100.end())->first + 100 << "} == height{" << height << "} is not equal");
|
||||
}
|
||||
m_last_144_blocks_every_100[height] = id;
|
||||
}
|
||||
//every 1000-th
|
||||
//every 100-th
|
||||
if (height % 1000 == 0)
|
||||
{
|
||||
//self check
|
||||
if (!m_last_144_blocks_every_1000.empty())
|
||||
{
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX((--m_last_144_blocks_every_1000.end())->first + 1000 == height, "Inernal error: (--m_last_144_blocks_every_1000.end())->first + 1000{" << (--m_last_144_blocks_every_1000.end())->first + 1000 << "} == height{" << height << "} is not equal");
|
||||
}
|
||||
m_last_144_blocks_every_1000[height] = id;
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet_chain_shortener::get_short_chain_history(std::list<crypto::hash>& ids)const
|
||||
{
|
||||
ids.clear();
|
||||
uint64_t i = 0;
|
||||
uint64_t sz = get_blockchain_current_size();
|
||||
if (!sz)
|
||||
return;
|
||||
|
||||
//first put last 10
|
||||
for (auto it = m_last_10_blocks.rbegin(); it != m_last_10_blocks.rend(); it++)
|
||||
{
|
||||
ids.push_back(it->second);
|
||||
i = it->first;
|
||||
}
|
||||
|
||||
uint64_t current_back_offset = m_last_10_blocks.size();
|
||||
//self check
|
||||
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<uint64_t, crypto::hash> 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.second);
|
||||
current_offset_distance *= 2;
|
||||
current_back_offset += current_offset_distance;
|
||||
}
|
||||
ids.push_back(m_genesis);
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
bool wallet_chain_shortener::lookup_item_around(uint64_t i, std::pair<uint64_t, crypto::hash>& result)const
|
||||
{
|
||||
//in which container we are looking for?
|
||||
uint64_t devider = 0;
|
||||
std::map<uint64_t, crypto::hash>* 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
|
||||
THROW_IF_FALSE_WALLET_INT_ERR_EX(it != pcontainer->end(),
|
||||
"Inernal error: index " << i << " not found for devider " << devider
|
||||
<< " pcontainer={" << pcontainer->begin()->first << ":" << (--pcontainer->end())->first << "}");
|
||||
result = *it;
|
||||
return true;
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void wallet_chain_shortener::check_if_block_matched(uint64_t i, const crypto::hash& id, bool& block_found, bool& block_matched, bool& full_reset_needed)const
|
||||
{
|
||||
if (!m_last_10_blocks.empty() && i > m_last_10_blocks.begin()->first)
|
||||
{
|
||||
//must be in short sequence (m_last_10_blocks)
|
||||
//self check
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX((--m_last_10_blocks.end())->first >= i,
|
||||
"Inernal error: index " << i << " is not located in expected range of m_last_10_blocks={"
|
||||
<< m_last_10_blocks.begin()->first << ":" << (--m_last_10_blocks.end())->first << "}");
|
||||
|
||||
auto it = m_last_10_blocks.find(i);
|
||||
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(it != m_last_10_blocks.end(),
|
||||
"Inernal error: filde to find index " << i << " in m_last_10_blocks={"
|
||||
<< m_last_10_blocks.begin()->first << ":" << (--m_last_10_blocks.end())->first << "}");
|
||||
|
||||
block_found = true;
|
||||
if (id == it->second)
|
||||
block_matched = true;
|
||||
else
|
||||
block_matched = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//lazy lookup
|
||||
std::pair<uint64_t, crypto::hash> result = AUTO_VAL_INIT(result);
|
||||
bool r = lookup_item_around(i, result);
|
||||
if (!r)
|
||||
{
|
||||
WLT_LOG_L0("Wallet is getting fully resynced due to unmatched block " << id << " at " << i);
|
||||
block_matched = block_found = false;
|
||||
full_reset_needed = true;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (result.first == i)
|
||||
{
|
||||
block_found = true;
|
||||
if (result.second == id)
|
||||
{
|
||||
block_matched = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
block_matched = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
block_found = false;
|
||||
block_matched = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------------------------------
|
||||
void clean_map_from_items_above(std::map<uint64_t, crypto::hash>& container, uint64_t height)
|
||||
{
|
||||
while (container.size() && (--container.end())->first > height)
|
||||
{
|
||||
container.erase(--container.end());
|
||||
}
|
||||
}
|
||||
void wallet_chain_shortener::detach(uint64_t height)
|
||||
{
|
||||
clean_map_from_items_above(m_last_10_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);
|
||||
}
|
||||
49
src/wallet/wallet_chain_shortener.h
Normal file
49
src/wallet/wallet_chain_shortener.h
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright (c) 2014-2018 Zano Project
|
||||
// Distributed under the MIT/X11 software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#pragma once
|
||||
#pragma once
|
||||
#include <memory>
|
||||
#include <boost/serialization/list.hpp>
|
||||
#include <boost/serialization/vector.hpp>
|
||||
#include <boost/serialization/deque.hpp>
|
||||
#include <boost/serialization/singleton.hpp>
|
||||
#include <boost/serialization/extended_type_info.hpp>
|
||||
#include <boost/serialization/shared_ptr.hpp>
|
||||
#include <atomic>
|
||||
#include <map>
|
||||
|
||||
#include "include_base_utils.h"
|
||||
#include "crypto/crypto.h"
|
||||
|
||||
|
||||
class wallet_chain_shortener
|
||||
{
|
||||
public:
|
||||
void push_new_block_id(const crypto::hash& id, uint64_t height);
|
||||
uint64_t get_top_block_height() const;
|
||||
uint64_t get_blockchain_current_size() const;
|
||||
void get_short_chain_history(std::list<crypto::hash>& ids)const;
|
||||
bool lookup_item_around(uint64_t i, std::pair<uint64_t, crypto::hash>& 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 clear();
|
||||
template <class t_archive>
|
||||
inline void serialize(t_archive &a, const unsigned int ver)
|
||||
{
|
||||
a & m_local_bc_size;
|
||||
a & m_genesis;
|
||||
a & m_last_10_blocks;
|
||||
a & m_last_144_blocks_every_10;
|
||||
a & m_last_144_blocks_every_100;
|
||||
a & m_last_144_blocks_every_1000;
|
||||
}
|
||||
private:
|
||||
std::atomic<uint64_t> m_local_bc_size; //temporary workaround
|
||||
crypto::hash m_genesis;
|
||||
std::map<uint64_t, crypto::hash> m_last_10_blocks;
|
||||
std::map<uint64_t, crypto::hash> m_last_144_blocks_every_10; //1 day
|
||||
std::map<uint64_t, crypto::hash> m_last_144_blocks_every_100; //10 days
|
||||
std::map<uint64_t, crypto::hash> m_last_144_blocks_every_1000; //100 days
|
||||
};
|
||||
|
|
@ -696,3 +696,22 @@ if (cond)
|
|||
LOG_ERROR(" (" << #cond << ") is FALSE. THROW EXCEPTION: wallet_common_error"); \
|
||||
tools::error::throw_wallet_ex<tools::error::wallet_common_error>(std::string(__FILE__ ":" STRINGIZE(__LINE__)), ss.str()); \
|
||||
}
|
||||
|
||||
|
||||
// wallet-specific logging functions
|
||||
#define WLT_LOG_L0(msg) LOG_PRINT_L0("[W:" << m_log_prefix << "] " << msg)
|
||||
#define WLT_LOG_L1(msg) LOG_PRINT_L1("[W:" << m_log_prefix << "] " << msg)
|
||||
#define WLT_LOG_L2(msg) LOG_PRINT_L2("[W:" << m_log_prefix << "] " << msg)
|
||||
#define WLT_LOG_L3(msg) LOG_PRINT_L3("[W:" << m_log_prefix << "] " << msg)
|
||||
#define WLT_LOG_L4(msg) LOG_PRINT_L4("[W:" << m_log_prefix << "] " << msg)
|
||||
#define WLT_LOG_ERROR(msg) LOG_ERROR("[W:" << m_log_prefix << "] " << msg)
|
||||
#define WLT_LOG_BLUE(msg, log_level) LOG_PRINT_BLUE("[W:" << m_log_prefix << "] " << msg, log_level)
|
||||
#define WLT_LOG_CYAN(msg, log_level) LOG_PRINT_CYAN("[W:" << m_log_prefix << "] " << msg, log_level)
|
||||
#define WLT_LOG_GREEN(msg, log_level) LOG_PRINT_GREEN("[W:" << m_log_prefix << "] " << msg, log_level)
|
||||
#define WLT_LOG_MAGENTA(msg, log_level) LOG_PRINT_MAGENTA("[W:" << m_log_prefix << "] " << msg, log_level)
|
||||
#define WLT_LOG_RED(msg, log_level) LOG_PRINT_RED("[W:" << m_log_prefix << "] " << msg, log_level)
|
||||
#define WLT_LOG_YELLOW(msg, log_level) LOG_PRINT_YELLOW("[W:" << m_log_prefix << "] " << msg, log_level)
|
||||
#define WLT_CHECK_AND_ASSERT_MES(expr, ret, msg) CHECK_AND_ASSERT_MES(expr, ret, "[W:" << m_log_prefix << "] " << msg)
|
||||
#define WLT_CHECK_AND_ASSERT_MES_NO_RET(expr, msg) CHECK_AND_ASSERT_MES_NO_RET(expr, "[W:" << m_log_prefix << "] " << msg)
|
||||
#define WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(cond, msg) THROW_IF_FALSE_WALLET_INT_ERR_EX(cond, "[W:" << m_log_prefix << "] " << msg)
|
||||
#define WLT_THROW_IF_FALSE_WALLET_CMN_ERR_EX(cond, msg) THROW_IF_FALSE_WALLET_CMN_ERR_EX(cond, "[W:" << m_log_prefix << "] " << msg)
|
||||
|
|
|
|||
|
|
@ -1188,7 +1188,7 @@ std::string wallets_manager::transfer(size_t wallet_id, const view::transfer_par
|
|||
if (tp.lock_time > CURRENCY_MAX_BLOCK_NUMBER)
|
||||
unlock_time = tp.lock_time;
|
||||
else
|
||||
unlock_time = w->get()->get_blockchain_current_height() + tp.lock_time;
|
||||
unlock_time = w->get()->get_blockchain_current_size() + tp.lock_time;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue