1
0
Fork 0
forked from lthn/blockchain

re-implemented detach blocks

This commit is contained in:
cryptozoidberg 2020-04-25 00:30:55 +02:00
parent 93d07e607f
commit caaca44f1e
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
4 changed files with 52 additions and 32 deletions

View file

@ -147,7 +147,7 @@ namespace currency
struct request
{
std::list<std::pair<uint64_t, crypto::hash> > 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<epee::pod_pair<uint64_t, crypto::hash> > 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)

View file

@ -1116,7 +1116,7 @@ bool simple_wallet::show_blockchain_height(const std::vector<std::string>& args)
bool simple_wallet::show_wallet_bcheight(const std::vector<std::string>& 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;
}

View file

@ -1070,8 +1070,8 @@ void wallet2::process_unconfirmed(const currency::transaction& tx, std::vector<s
void wallet2::process_new_blockchain_entry(const currency::block& b, const currency::block_direct_data_entry& bche, const crypto::hash& bl_id, uint64_t height)
{
//handle transactions from new block
THROW_IF_TRUE_WALLET_EX(height != get_blockchain_current_height(), error::wallet_internal_error,
"current_index=" + std::to_string(height) + ", get_blockchain_current_height()=" + std::to_string(get_blockchain_current_height()));
THROW_IF_TRUE_WALLET_EX(height != get_blockchain_current_size(), error::wallet_internal_error,
"current_index=" + std::to_string(height) + ", get_blockchain_current_height()=" + std::to_string(get_blockchain_current_size()));
//optimization: seeking only for blocks that are not older then the wallet creation time plus 1 day. 1 day is for possible user incorrect time setup
if (b.timestamp + 60 * 60 * 24 > m_account.get_createtime())
@ -1092,7 +1092,7 @@ void wallet2::process_new_blockchain_entry(const currency::block& b, const curre
WLT_LOG_L3( "Skipped block by timestamp, height: " << height << ", block time " << b.timestamp << ", account time " << m_account.get_createtime());
}
push_new_block_id(bl_id, height); //m_blockchain.push_back(bl_id);
++m_local_bc_height;
m_local_bc_size = height + 1;
m_last_bc_timestamp = b.timestamp;
if (!is_pos_block(b))
m_last_pow_block_h = height;
@ -1106,7 +1106,7 @@ void wallet2::push_new_block_id(const crypto::hash& id, uint64_t height)
//self check
if (!m_last_10_blocks.empty())
{
WLT_THROW_IF_FALSE_WALLET_INT_ERR_EX(get_blockchain_current_height() == height, "Inernal error: get_blockchain_current_height(){" << get_blockchain_current_height() << "} == height{" << height << "} is not equal");
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;
@ -1215,7 +1215,7 @@ void wallet2::get_short_chain_history(std::list<epee::pod_pair<uint64_t, crypto:
{
ids.clear();
uint64_t i = 0;
uint64_t sz = get_blockchain_current_height();
uint64_t sz = get_blockchain_current_size();
if (!sz)
return;
@ -1289,9 +1289,9 @@ void wallet2::pull_blocks(size_t& blocks_added, std::atomic<bool>& 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<bool>& 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<bool>& 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<bool>& 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<bool>& 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<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);
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;
}

View file

@ -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 <class t_archive>
@ -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<uint64_t, crypto::hash>& result);
void get_short_chain_history(std::list<epee::pod_pair<uint64_t, crypto::hash> >& 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<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
std::atomic<uint64_t> m_local_bc_height; //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;