rpc: rework to avoid repeated calculations in get_blocks.bin

This commit is contained in:
moneromooo-monero 2018-04-16 20:16:00 +01:00
parent ed2c81ed95
commit a830db2577
No known key found for this signature in database
GPG key ID: 686F07454D6CEFC3
6 changed files with 36 additions and 40 deletions

View file

@ -2242,7 +2242,7 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
// find split point between ours and foreign blockchain (or start at // find split point between ours and foreign blockchain (or start at
// blockchain height <req_start_block>), and return up to max_count FULL // blockchain height <req_start_block>), and return up to max_count FULL
// blocks by reference. // blocks by reference.
bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<cryptonote::blobdata, std::vector<cryptonote::blobdata> > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, size_t max_count) const bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_count) const
{ {
LOG_PRINT_L3("Blockchain::" << __func__); LOG_PRINT_L3("Blockchain::" << __func__);
CRITICAL_REGION_LOCAL(m_blockchain_lock); CRITICAL_REGION_LOCAL(m_blockchain_lock);
@ -2272,15 +2272,24 @@ bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, cons
for(size_t i = start_height; i < total_height && count < max_count && (size < FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE || count < 3); i++, count++) for(size_t i = start_height; i < total_height && count < max_count && (size < FIND_BLOCKCHAIN_SUPPLEMENT_MAX_SIZE || count < 3); i++, count++)
{ {
blocks.resize(blocks.size()+1); blocks.resize(blocks.size()+1);
blocks.back().first = m_db->get_block_blob_from_height(i); blocks.back().first.first = m_db->get_block_blob_from_height(i);
block b; block b;
CHECK_AND_ASSERT_MES(parse_and_validate_block_from_blob(blocks.back().first, b), false, "internal error, invalid block"); CHECK_AND_ASSERT_MES(parse_and_validate_block_from_blob(blocks.back().first.first, b), false, "internal error, invalid block");
blocks.back().first.second = get_miner_tx_hash ? cryptonote::get_transaction_hash(b.miner_tx) : crypto::null_hash;
std::vector<crypto::hash> mis; std::vector<crypto::hash> mis;
get_transactions_blobs(b.tx_hashes, blocks.back().second, mis, pruned); std::vector<cryptonote::blobdata> txs;
get_transactions_blobs(b.tx_hashes, txs, mis, pruned);
CHECK_AND_ASSERT_MES(!mis.size(), false, "internal error, transaction from block not found"); CHECK_AND_ASSERT_MES(!mis.size(), false, "internal error, transaction from block not found");
size += blocks.back().first.size(); size += blocks.back().first.first.size();
for (const auto &t: blocks.back().second) for (const auto &t: txs)
size += t.size(); size += t.size();
CHECK_AND_ASSERT_MES(txs.size() == b.tx_hashes.size(), false, "mismatched sizes of b.tx_hashes and txs");
blocks.back().second.reserve(txs.size());
for (size_t i = 0; i < txs.size(); ++i)
{
blocks.back().second.push_back(std::make_pair(b.tx_hashes[i], std::move(txs[i])));
}
} }
m_db->block_txn_stop(); m_db->block_txn_stop();
return true; return true;

View file

@ -420,7 +420,7 @@ namespace cryptonote
* *
* @return true if a block found in common or req_start_block specified, else false * @return true if a block found in common or req_start_block specified, else false
*/ */
bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<cryptonote::blobdata, std::vector<cryptonote::blobdata> > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, size_t max_count) const; bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_count) const;
/** /**
* @brief retrieves a set of blocks and their transactions, and possibly other transactions * @brief retrieves a set of blocks and their transactions, and possibly other transactions

View file

@ -1055,9 +1055,9 @@ namespace cryptonote
return m_blockchain_storage.find_blockchain_supplement(qblock_ids, resp); return m_blockchain_storage.find_blockchain_supplement(qblock_ids, resp);
} }
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
bool core::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<cryptonote::blobdata, std::vector<cryptonote::blobdata> > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, size_t max_count) const bool core::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_count) const
{ {
return m_blockchain_storage.find_blockchain_supplement(req_start_block, qblock_ids, blocks, total_height, start_height, pruned, max_count); return m_blockchain_storage.find_blockchain_supplement(req_start_block, qblock_ids, blocks, total_height, start_height, pruned, get_miner_tx_hash, max_count);
} }
//----------------------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------------------
bool core::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res) const bool core::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res) const

View file

@ -516,7 +516,7 @@ namespace cryptonote
* *
* @note see Blockchain::find_blockchain_supplement(const uint64_t, const std::list<crypto::hash>&, std::vector<std::pair<cryptonote::blobdata, std::vector<transaction> > >&, uint64_t&, uint64_t&, size_t) const * @note see Blockchain::find_blockchain_supplement(const uint64_t, const std::list<crypto::hash>&, std::vector<std::pair<cryptonote::blobdata, std::vector<transaction> > >&, uint64_t&, uint64_t&, size_t) const
*/ */
bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<cryptonote::blobdata, std::vector<cryptonote::blobdata> > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, size_t max_count) const; bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, bool get_miner_tx_hash, size_t max_count) const;
/** /**
* @brief gets some stats about the daemon * @brief gets some stats about the daemon

View file

@ -226,9 +226,9 @@ namespace cryptonote
if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCKS_FAST>(invoke_http_mode::BIN, "/getblocks.bin", req, res, r)) if (use_bootstrap_daemon_if_necessary<COMMAND_RPC_GET_BLOCKS_FAST>(invoke_http_mode::BIN, "/getblocks.bin", req, res, r))
return r; return r;
std::vector<std::pair<cryptonote::blobdata, std::vector<cryptonote::blobdata> > > bs; std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata> > > > bs;
if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, bs, res.current_height, res.start_height, req.prune, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT)) if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, bs, res.current_height, res.start_height, req.prune, !req.no_miner_tx, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT))
{ {
res.status = "Failed"; res.status = "Failed";
return false; return false;
@ -240,46 +240,33 @@ namespace cryptonote
for(auto& bd: bs) for(auto& bd: bs)
{ {
res.blocks.resize(res.blocks.size()+1); res.blocks.resize(res.blocks.size()+1);
res.blocks.back().block = bd.first; res.blocks.back().block = bd.first.first;
pruned_size += bd.first.size(); pruned_size += bd.first.first.size();
unpruned_size += bd.first.size(); unpruned_size += bd.first.first.size();
res.output_indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices()); res.output_indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices());
res.output_indices.back().indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::tx_output_indices()); res.output_indices.back().indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::tx_output_indices());
block b;
if (!parse_and_validate_block_from_blob(bd.first, b))
{
res.status = "Invalid block";
return false;
}
if (!req.no_miner_tx) if (!req.no_miner_tx)
{ {
bool r = m_core.get_tx_outputs_gindexs(get_transaction_hash(b.miner_tx), res.output_indices.back().indices.back().indices); bool r = m_core.get_tx_outputs_gindexs(bd.first.second, res.output_indices.back().indices.back().indices);
if (!r) if (!r)
{ {
res.status = "Failed"; res.status = "Failed";
return false; return false;
} }
} }
if(b.tx_hashes.size() != bd.second.size())
{
MERROR("block " << get_block_hash(b) << ": tx_hashes.size() " << b.tx_hashes.size() << ", bd.second.size() " << bd.second.size());
res.status = "Failed";
return false;
}
size_t txidx = 0;
ntxes += bd.second.size(); ntxes += bd.second.size();
res.blocks.back().txs.reserve(bd.second.size()); res.blocks.back().txs.reserve(bd.second.size());
res.output_indices.back().indices.reserve(bd.second.size()); res.output_indices.back().indices.reserve(bd.second.size());
for (std::vector<cryptonote::blobdata>::iterator i = bd.second.begin(); i != bd.second.end(); ++i) for (std::vector<std::pair<crypto::hash, cryptonote::blobdata>>::iterator i = bd.second.begin(); i != bd.second.end(); ++i)
{ {
unpruned_size += i->size(); unpruned_size += i->second.size();
res.blocks.back().txs.push_back(std::move(*i)); res.blocks.back().txs.push_back(std::move(i->second));
i->clear(); i->second.clear();
i->shrink_to_fit(); i->second.shrink_to_fit();
pruned_size += res.blocks.back().txs.back().size(); pruned_size += res.blocks.back().txs.back().size();
res.output_indices.back().indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::tx_output_indices()); res.output_indices.back().indices.push_back(COMMAND_RPC_GET_BLOCKS_FAST::tx_output_indices());
bool r = m_core.get_tx_outputs_gindexs(b.tx_hashes[txidx++], res.output_indices.back().indices.back().indices); bool r = m_core.get_tx_outputs_gindexs(i->first, res.output_indices.back().indices.back().indices);
if (!r) if (!r)
{ {
res.status = "Failed"; res.status = "Failed";

View file

@ -50,9 +50,9 @@ namespace rpc
void DaemonHandler::handle(const GetBlocksFast::Request& req, GetBlocksFast::Response& res) void DaemonHandler::handle(const GetBlocksFast::Request& req, GetBlocksFast::Response& res)
{ {
std::vector<std::pair<blobdata, std::vector<blobdata> > > blocks; std::vector<std::pair<std::pair<blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, blobdata> > > > blocks;
if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, blocks, res.current_height, res.start_height, req.prune, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT)) if(!m_core.find_blockchain_supplement(req.start_height, req.block_ids, blocks, res.current_height, res.start_height, req.prune, true, COMMAND_RPC_GET_BLOCKS_FAST_MAX_COUNT))
{ {
res.status = Message::STATUS_FAILED; res.status = Message::STATUS_FAILED;
res.error_details = "core::find_blockchain_supplement() returned false"; res.error_details = "core::find_blockchain_supplement() returned false";
@ -69,7 +69,7 @@ namespace rpc
{ {
cryptonote::rpc::block_with_transactions& bwt = res.blocks[block_count]; cryptonote::rpc::block_with_transactions& bwt = res.blocks[block_count];
if (!parse_and_validate_block_from_blob(it->first, bwt.block)) if (!parse_and_validate_block_from_blob(it->first.first, bwt.block))
{ {
res.blocks.clear(); res.blocks.clear();
res.output_indices.clear(); res.output_indices.clear();
@ -87,10 +87,10 @@ namespace rpc
return; return;
} }
std::vector<transaction> txs; std::vector<transaction> txs;
for (const auto& blob : it->second) for (const auto& p : it->second)
{ {
txs.resize(txs.size() + 1); txs.resize(txs.size() + 1);
if (!parse_and_validate_tx_from_blob(blob, txs.back())) if (!parse_and_validate_tx_from_blob(p.second, txs.back()))
{ {
res.blocks.clear(); res.blocks.clear();
res.output_indices.clear(); res.output_indices.clear();