blockchain: speedup fetching pruned contiguous tx blobs
About twice as fast, very roughly
This commit is contained in:
parent
fe3f6a3e6b
commit
08635a0875
|
@ -1252,6 +1252,22 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const = 0;
|
virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief fetches a number of pruned transaction blob from the given hash, in canonical blockchain order
|
||||||
|
*
|
||||||
|
* The subclass should return the pruned transactions stored from the one with the given
|
||||||
|
* hash.
|
||||||
|
*
|
||||||
|
* If the first transaction does not exist, the subclass should return false.
|
||||||
|
* If the first transaction exists, but there are fewer transactions starting with it
|
||||||
|
* than requested, the subclass should return false.
|
||||||
|
*
|
||||||
|
* @param h the hash to look for
|
||||||
|
*
|
||||||
|
* @return true iff the transactions were found
|
||||||
|
*/
|
||||||
|
virtual bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief fetches the prunable transaction blob with the given hash
|
* @brief fetches the prunable transaction blob with the given hash
|
||||||
*
|
*
|
||||||
|
|
|
@ -3033,6 +3033,48 @@ bool BlockchainLMDB::get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobd
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BlockchainLMDB::get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const
|
||||||
|
{
|
||||||
|
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||||
|
check_open();
|
||||||
|
|
||||||
|
if (!count)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
TXN_PREFIX_RDONLY();
|
||||||
|
RCURSOR(tx_indices);
|
||||||
|
RCURSOR(txs_pruned);
|
||||||
|
|
||||||
|
bd.reserve(bd.size() + count);
|
||||||
|
|
||||||
|
MDB_val_set(v, h);
|
||||||
|
MDB_val result;
|
||||||
|
int res = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH);
|
||||||
|
if (res == MDB_NOTFOUND)
|
||||||
|
return false;
|
||||||
|
if (res)
|
||||||
|
throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx from hash", res).c_str()));
|
||||||
|
|
||||||
|
const txindex *tip = (const txindex *)v.mv_data;
|
||||||
|
const uint64_t id = tip->data.tx_id;
|
||||||
|
MDB_val_set(val_tx_id, id);
|
||||||
|
MDB_cursor_op op = MDB_SET;
|
||||||
|
while (count--)
|
||||||
|
{
|
||||||
|
res = mdb_cursor_get(m_cur_txs_pruned, &val_tx_id, &result, op);
|
||||||
|
op = MDB_NEXT;
|
||||||
|
if (res == MDB_NOTFOUND)
|
||||||
|
return false;
|
||||||
|
if (res)
|
||||||
|
throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx blob", res).c_str()));
|
||||||
|
bd.emplace_back(reinterpret_cast<char*>(result.mv_data), result.mv_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
TXN_POSTFIX_RDONLY();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool BlockchainLMDB::get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &bd) const
|
bool BlockchainLMDB::get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &bd) const
|
||||||
{
|
{
|
||||||
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
LOG_PRINT_L3("BlockchainLMDB::" << __func__);
|
||||||
|
|
|
@ -254,6 +254,7 @@ public:
|
||||||
|
|
||||||
virtual bool get_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const;
|
virtual bool get_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const;
|
||||||
virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const;
|
virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const;
|
||||||
|
virtual bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const;
|
||||||
virtual bool get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const;
|
virtual bool get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const;
|
||||||
virtual bool get_prunable_tx_hash(const crypto::hash& tx_hash, crypto::hash &prunable_hash) const;
|
virtual bool get_prunable_tx_hash(const crypto::hash& tx_hash, crypto::hash &prunable_hash) const;
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,7 @@ public:
|
||||||
virtual cryptonote::blobdata get_block_blob(const crypto::hash& h) const override { return cryptonote::blobdata(); }
|
virtual cryptonote::blobdata get_block_blob(const crypto::hash& h) const override { return cryptonote::blobdata(); }
|
||||||
virtual bool get_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override { return false; }
|
virtual bool get_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override { return false; }
|
||||||
virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override { return false; }
|
virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override { return false; }
|
||||||
|
virtual bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const { return false; }
|
||||||
virtual bool get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override { return false; }
|
virtual bool get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override { return false; }
|
||||||
virtual bool get_prunable_tx_hash(const crypto::hash& tx_hash, crypto::hash &prunable_hash) const override { return false; }
|
virtual bool get_prunable_tx_hash(const crypto::hash& tx_hash, crypto::hash &prunable_hash) const override { return false; }
|
||||||
virtual uint64_t get_block_height(const crypto::hash& h) const override { return 0; }
|
virtual uint64_t get_block_height(const crypto::hash& h) const override { return 0; }
|
||||||
|
|
|
@ -2498,10 +2498,17 @@ bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, cons
|
||||||
block b;
|
block b;
|
||||||
CHECK_AND_ASSERT_MES(parse_and_validate_block_from_blob(blocks.back().first.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;
|
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<cryptonote::blobdata> txs;
|
std::vector<cryptonote::blobdata> txs;
|
||||||
get_transactions_blobs(b.tx_hashes, txs, mis, pruned);
|
if (pruned)
|
||||||
CHECK_AND_ASSERT_MES(!mis.size(), false, "internal error, transaction from block not found");
|
{
|
||||||
|
CHECK_AND_ASSERT_MES(m_db->get_pruned_tx_blobs_from(b.tx_hashes.front(), b.tx_hashes.size(), txs), false, "Failed to retrieve all transactions needed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::vector<crypto::hash> mis;
|
||||||
|
get_transactions_blobs(b.tx_hashes, txs, mis, pruned);
|
||||||
|
CHECK_AND_ASSERT_MES(!mis.size(), false, "internal error, transaction from block not found");
|
||||||
|
}
|
||||||
size += blocks.back().first.first.size();
|
size += blocks.back().first.first.size();
|
||||||
for (const auto &t: txs)
|
for (const auto &t: txs)
|
||||||
size += t.size();
|
size += t.size();
|
||||||
|
|
Loading…
Reference in New Issue