1
0
Fork 0
forked from lthn/blockchain

implemented new items lookup and get_short_chain_history

This commit is contained in:
cryptozoidberg 2020-04-24 19:18:19 +02:00
parent 4825b7c012
commit 3b975d899e
No known key found for this signature in database
GPG key ID: 22DEB97A54C6FDEC
4 changed files with 136 additions and 27 deletions

View file

@ -84,6 +84,12 @@ namespace epee
return res;
}
//-------------------------------------------------------------------------------------------------------------------
#pragma pack(push, 1)
template<class first_t, class second_t>
struct pod_pair
{
first_t first;
second_t second;
};
#pragma pack(pop)
}

View file

@ -141,6 +141,36 @@ namespace currency
typedef COMMAND_RPC_GET_BLOCKS_FAST_T<block_complete_entry> COMMAND_RPC_GET_BLOCKS_FAST;
typedef COMMAND_RPC_GET_BLOCKS_FAST_T<block_direct_data_entry> COMMAND_RPC_GET_BLOCKS_DIRECT;
template<class t_block_complete_entry>
struct COMMAND_RPC_GET_BLOCKS_FUZZY_FAST_T
{
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 */
BEGIN_KV_SERIALIZE_MAP()
KV_SERIALIZE_CONTAINER_POD_AS_BLOB(block_ids)
END_KV_SERIALIZE_MAP()
};
struct response
{
std::list<t_block_complete_entry> 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<block_complete_entry> COMMAND_RPC_GET_BLOCKS_FUZZY_FAST;
typedef COMMAND_RPC_GET_BLOCKS_FUZZY_FAST_T<block_direct_data_entry> COMMAND_RPC_GET_BLOCKS_FUZZY_DIRECT;
//-----------------------------------------------

View file

@ -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<crypto::hash>& ids)
// void wallet2::get_short_chain_history(std::list<crypto::hash>& 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<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: 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<epee::pod_pair<uint64_t, crypto::hash> >& 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<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);
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<bool>& 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)

View file

@ -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<crypto::hash>& ids);
bool extract_offers_from_transfer_entry(size_t i, std::unordered_map<crypto::hash, bc_services::offer_details_ex>& offers_local);
bool select_my_offers(std::list<bc_services::offer_details_ex>& 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<uint64_t, crypto::hash>& result);
void get_short_chain_history(std::list<std::pair<uint64_t, crypto::hash> >& ids);
currency::account_base m_account;
bool m_watch_only;