Merge pull request #5346

c84ea299 cryptonote_basic: some more minor speedups (moneromooo-monero)
e40eb2ad cryptonote_basic: speedup calculate_block_hash (moneromooo-monero)
547a9708 cryptonote: block parsing + hash calculation speedup (moneromooo-monero)
11604b6d blockchain: avoid unneeded block copy (moneromooo-monero)
8461df04 save some database calls when getting top block hash and height (moneromooo-monero)
3bbc3661 Avoid repeated (de)serialization when syncing (moneromooo-monero)
This commit is contained in:
Riccardo Spagni 2019-04-06 15:59:43 +02:00
commit 4ac78e1612
No known key found for this signature in database
GPG Key ID: 55432DF31CCD4FCD
6 changed files with 65 additions and 20 deletions

View File

@ -1090,7 +1090,14 @@ namespace cryptonote
// we still need the size // we still need the size
if (blob_size) if (blob_size)
*blob_size = get_object_blobsize(t); {
if (!t.is_blob_size_valid())
{
t.blob_size = blob.size();
t.set_blob_size_valid(true);
}
*blob_size = t.blob_size;
}
return true; return true;
} }
@ -1143,21 +1150,37 @@ namespace cryptonote
return blob; return blob;
} }
//--------------------------------------------------------------- //---------------------------------------------------------------
bool calculate_block_hash(const block& b, crypto::hash& res) bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata *blob)
{ {
blobdata bd;
if (!blob)
{
bd = block_to_blob(b);
blob = &bd;
}
bool hash_result = get_object_hash(get_block_hashing_blob(b), res);
if (!hash_result)
return false;
if (b.miner_tx.vin.size() == 1 && b.miner_tx.vin[0].type() == typeid(cryptonote::txin_gen))
{
const cryptonote::txin_gen &txin_gen = boost::get<cryptonote::txin_gen>(b.miner_tx.vin[0]);
if (txin_gen.height != 202612)
return true;
}
// EXCEPTION FOR BLOCK 202612 // EXCEPTION FOR BLOCK 202612
const std::string correct_blob_hash_202612 = "3a8a2b3a29b50fc86ff73dd087ea43c6f0d6b8f936c849194d5c84c737903966"; const std::string correct_blob_hash_202612 = "3a8a2b3a29b50fc86ff73dd087ea43c6f0d6b8f936c849194d5c84c737903966";
const std::string existing_block_id_202612 = "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698"; const std::string existing_block_id_202612 = "bbd604d2ba11ba27935e006ed39c9bfdd99b76bf4a50654bc1e1e61217962698";
crypto::hash block_blob_hash = get_blob_hash(block_to_blob(b)); crypto::hash block_blob_hash = get_blob_hash(*blob);
if (string_tools::pod_to_hex(block_blob_hash) == correct_blob_hash_202612) if (string_tools::pod_to_hex(block_blob_hash) == correct_blob_hash_202612)
{ {
string_tools::hex_to_pod(existing_block_id_202612, res); string_tools::hex_to_pod(existing_block_id_202612, res);
return true; return true;
} }
bool hash_result = get_object_hash(get_block_hashing_blob(b), res);
if (hash_result)
{ {
// make sure that we aren't looking at a block with the 202612 block id but not the correct blobdata // make sure that we aren't looking at a block with the 202612 block id but not the correct blobdata
if (string_tools::pod_to_hex(res) == existing_block_id_202612) if (string_tools::pod_to_hex(res) == existing_block_id_202612)
@ -1200,9 +1223,9 @@ namespace cryptonote
bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height) bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height)
{ {
// block 202612 bug workaround // block 202612 bug workaround
const std::string longhash_202612 = "84f64766475d51837ac9efbef1926486e58563c95a19fef4aec3254f03000000";
if (height == 202612) if (height == 202612)
{ {
static const std::string longhash_202612 = "84f64766475d51837ac9efbef1926486e58563c95a19fef4aec3254f03000000";
string_tools::hex_to_pod(longhash_202612, res); string_tools::hex_to_pod(longhash_202612, res);
return true; return true;
} }
@ -1239,7 +1262,7 @@ namespace cryptonote
return p; return p;
} }
//--------------------------------------------------------------- //---------------------------------------------------------------
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b) bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash *block_hash)
{ {
std::stringstream ss; std::stringstream ss;
ss << b_blob; ss << b_blob;
@ -1248,9 +1271,26 @@ namespace cryptonote
CHECK_AND_ASSERT_MES(r, false, "Failed to parse block from blob"); CHECK_AND_ASSERT_MES(r, false, "Failed to parse block from blob");
b.invalidate_hashes(); b.invalidate_hashes();
b.miner_tx.invalidate_hashes(); b.miner_tx.invalidate_hashes();
if (block_hash)
{
calculate_block_hash(b, *block_hash, &b_blob);
++block_hashes_calculated_count;
b.hash = *block_hash;
b.set_hash_valid(true);
}
return true; return true;
} }
//--------------------------------------------------------------- //---------------------------------------------------------------
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b)
{
return parse_and_validate_block_from_blob(b_blob, b, NULL);
}
//---------------------------------------------------------------
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash &block_hash)
{
return parse_and_validate_block_from_blob(b_blob, b, &block_hash);
}
//---------------------------------------------------------------
blobdata block_to_blob(const block& b) blobdata block_to_blob(const block& b)
{ {
return t_serializable_object_to_blob(b); return t_serializable_object_to_blob(b);
@ -1286,6 +1326,7 @@ namespace cryptonote
crypto::hash get_tx_tree_hash(const block& b) crypto::hash get_tx_tree_hash(const block& b)
{ {
std::vector<crypto::hash> txs_ids; std::vector<crypto::hash> txs_ids;
txs_ids.reserve(1 + b.tx_hashes.size());
crypto::hash h = null_hash; crypto::hash h = null_hash;
size_t bl_sz = 0; size_t bl_sz = 0;
get_transaction_hash(b.miner_tx, h, bl_sz); get_transaction_hash(b.miner_tx, h, bl_sz);

View File

@ -114,12 +114,14 @@ namespace cryptonote
crypto::hash get_pruned_transaction_hash(const transaction& t, const crypto::hash &pruned_data_hash); crypto::hash get_pruned_transaction_hash(const transaction& t, const crypto::hash &pruned_data_hash);
blobdata get_block_hashing_blob(const block& b); blobdata get_block_hashing_blob(const block& b);
bool calculate_block_hash(const block& b, crypto::hash& res); bool calculate_block_hash(const block& b, crypto::hash& res, const blobdata *blob = NULL);
bool get_block_hash(const block& b, crypto::hash& res); bool get_block_hash(const block& b, crypto::hash& res);
crypto::hash get_block_hash(const block& b); crypto::hash get_block_hash(const block& b);
bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height); bool get_block_longhash(const block& b, crypto::hash& res, uint64_t height);
crypto::hash get_block_longhash(const block& b, uint64_t height); crypto::hash get_block_longhash(const block& b, uint64_t height);
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash *block_hash);
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b); bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b);
bool parse_and_validate_block_from_blob(const blobdata& b_blob, block& b, crypto::hash &block_hash);
bool get_inputs_money_amount(const transaction& tx, uint64_t& money); bool get_inputs_money_amount(const transaction& tx, uint64_t& money);
uint64_t get_outs_money_amount(const transaction& tx); uint64_t get_outs_money_amount(const transaction& tx);
bool check_inputs_types_supported(const transaction& tx); bool check_inputs_types_supported(const transaction& tx);

View File

@ -3176,6 +3176,7 @@ bool Blockchain::check_fee(size_t tx_weight, uint64_t fee) const
if (version >= HF_VERSION_DYNAMIC_FEE) if (version >= HF_VERSION_DYNAMIC_FEE)
{ {
median = m_current_block_cumul_weight_limit / 2; median = m_current_block_cumul_weight_limit / 2;
const uint64_t blockchain_height = m_db->height();
already_generated_coins = blockchain_height ? m_db->get_block_already_generated_coins(blockchain_height - 1) : 0; already_generated_coins = blockchain_height ? m_db->get_block_already_generated_coins(blockchain_height - 1) : 0;
if (!get_block_reward(median, 1, already_generated_coins, base_reward, version)) if (!get_block_reward(median, 1, already_generated_coins, base_reward, version))
return false; return false;
@ -4332,8 +4333,9 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
for (unsigned int j = 0; j < batches; j++, ++blockidx) for (unsigned int j = 0; j < batches; j++, ++blockidx)
{ {
block &block = blocks[blockidx]; block &block = blocks[blockidx];
crypto::hash block_hash;
if (!parse_and_validate_block_from_blob(it->block, block)) if (!parse_and_validate_block_from_blob(it->block, block, block_hash))
return false; return false;
// check first block and skip all blocks if its not chained properly // check first block and skip all blocks if its not chained properly
@ -4346,7 +4348,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
return true; return true;
} }
} }
if (have_block(get_block_hash(block))) if (have_block(block_hash))
blocks_exist = true; blocks_exist = true;
std::advance(it, 1); std::advance(it, 1);
@ -4356,11 +4358,12 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
for (unsigned i = 0; i < extra && !blocks_exist; i++, blockidx++) for (unsigned i = 0; i < extra && !blocks_exist; i++, blockidx++)
{ {
block &block = blocks[blockidx]; block &block = blocks[blockidx];
crypto::hash block_hash;
if (!parse_and_validate_block_from_blob(it->block, block)) if (!parse_and_validate_block_from_blob(it->block, block, block_hash))
return false; return false;
if (have_block(get_block_hash(block))) if (have_block(block_hash))
blocks_exist = true; blocks_exist = true;
std::advance(it, 1); std::advance(it, 1);

View File

@ -1432,7 +1432,8 @@ namespace cryptonote
block lb; block lb;
if (!b) if (!b)
{ {
if(!parse_and_validate_block_from_blob(block_blob, lb)) crypto::hash block_hash;
if(!parse_and_validate_block_from_blob(block_blob, lb, block_hash))
{ {
LOG_PRINT_L1("Failed to parse and validate new block"); LOG_PRINT_L1("Failed to parse and validate new block");
bvc.m_verifivation_failed = true; bvc.m_verifivation_failed = true;

View File

@ -995,7 +995,8 @@ namespace cryptonote
return 1; return 1;
} }
if(!parse_and_validate_block_from_blob(block_entry.block, b)) crypto::hash block_hash;
if(!parse_and_validate_block_from_blob(block_entry.block, b, block_hash))
{ {
LOG_ERROR_CCONTEXT("sent wrong block: failed to parse and validate block: " LOG_ERROR_CCONTEXT("sent wrong block: failed to parse and validate block: "
<< epee::string_tools::buff_to_hex_nodelimer(block_entry.block) << ", dropping connection"); << epee::string_tools::buff_to_hex_nodelimer(block_entry.block) << ", dropping connection");
@ -1014,7 +1015,6 @@ namespace cryptonote
if (start_height == std::numeric_limits<uint64_t>::max()) if (start_height == std::numeric_limits<uint64_t>::max())
start_height = boost::get<txin_gen>(b.miner_tx.vin[0]).height; start_height = boost::get<txin_gen>(b.miner_tx.vin[0]).height;
const crypto::hash block_hash = get_block_hash(b);
auto req_it = context.m_requested_objects.find(block_hash); auto req_it = context.m_requested_objects.find(block_hash);
if(req_it == context.m_requested_objects.end()) if(req_it == context.m_requested_objects.end())
{ {
@ -1121,13 +1121,13 @@ namespace cryptonote
<< ", we need " << previous_height); << ", we need " << previous_height);
block new_block; block new_block;
if (!parse_and_validate_block_from_blob(blocks.back().block, new_block)) crypto::hash last_block_hash;
if (!parse_and_validate_block_from_blob(blocks.back().block, new_block, last_block_hash))
{ {
MERROR(context << "Failed to parse block, but it should already have been parsed"); MERROR(context << "Failed to parse block, but it should already have been parsed");
m_block_queue.remove_spans(span_connection_id, start_height); m_block_queue.remove_spans(span_connection_id, start_height);
continue; continue;
} }
const crypto::hash last_block_hash = cryptonote::get_block_hash(new_block);
if (m_core.have_block(last_block_hash)) if (m_core.have_block(last_block_hash))
{ {
const uint64_t subchain_height = start_height + blocks.size(); const uint64_t subchain_height = start_height + blocks.size();

View File

@ -2348,9 +2348,7 @@ void wallet2::get_short_chain_history(std::list<crypto::hash>& ids, uint64_t gra
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
void wallet2::parse_block_round(const cryptonote::blobdata &blob, cryptonote::block &bl, crypto::hash &bl_id, bool &error) const void wallet2::parse_block_round(const cryptonote::blobdata &blob, cryptonote::block &bl, crypto::hash &bl_id, bool &error) const
{ {
error = !cryptonote::parse_and_validate_block_from_blob(blob, bl); error = !cryptonote::parse_and_validate_block_from_blob(blob, bl, bl_id);
if (!error)
bl_id = get_block_hash(bl);
} }
//---------------------------------------------------------------------------------------------------- //----------------------------------------------------------------------------------------------------
void wallet2::pull_blocks(uint64_t start_height, uint64_t &blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::vector<cryptonote::block_complete_entry> &blocks, std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> &o_indices) void wallet2::pull_blocks(uint64_t start_height, uint64_t &blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::vector<cryptonote::block_complete_entry> &blocks, std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> &o_indices)