aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_core')
-rw-r--r--src/cryptonote_core/blockchain.cpp66
-rw-r--r--src/cryptonote_core/blockchain.h6
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp8
-rw-r--r--src/cryptonote_core/cryptonote_core.h3
-rw-r--r--src/cryptonote_core/tx_pool.cpp35
-rw-r--r--src/cryptonote_core/tx_pool.h6
6 files changed, 78 insertions, 46 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index e908c2012..bfc5dbbe0 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -229,7 +229,7 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke
{
try
{
- m_db->get_output_key(tx_in_to_key.amount, absolute_offsets, outputs, true);
+ m_db->get_output_key(epee::span<const uint64_t>(&tx_in_to_key.amount, 1), absolute_offsets, outputs, true);
if (absolute_offsets.size() != outputs.size())
{
MERROR_VER("Output does not exist! amount = " << tx_in_to_key.amount);
@@ -255,7 +255,7 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke
add_offsets.push_back(absolute_offsets[i]);
try
{
- m_db->get_output_key(tx_in_to_key.amount, add_offsets, add_outputs, true);
+ m_db->get_output_key(epee::span<const uint64_t>(&tx_in_to_key.amount, 1), add_offsets, add_outputs, true);
if (add_offsets.size() != add_outputs.size())
{
MERROR_VER("Output does not exist! amount = " << tx_in_to_key.amount);
@@ -831,6 +831,7 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
std::vector<uint64_t> timestamps;
std::vector<difficulty_type> difficulties;
auto height = m_db->height();
+ top_hash = get_tail_id(); // get it again now that we have the lock
// ND: Speedup
// 1. Keep a list of the last 735 (or less) blocks that is used to compute difficulty,
// then when the next block difficulty is queried, push the latest height data and
@@ -853,7 +854,7 @@ difficulty_type Blockchain::get_difficulty_for_next_block()
}
else
{
- size_t offset = height - std::min < size_t > (height, static_cast<size_t>(DIFFICULTY_BLOCKS_COUNT));
+ uint64_t offset = height - std::min <uint64_t> (height, static_cast<uint64_t>(DIFFICULTY_BLOCKS_COUNT));
if (offset == 0)
++offset;
@@ -1766,16 +1767,34 @@ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMA
res.outs.clear();
res.outs.reserve(req.outputs.size());
+
+ std::vector<cryptonote::output_data_t> data;
try
{
+ std::vector<uint64_t> amounts, offsets;
+ amounts.reserve(req.outputs.size());
+ offsets.reserve(req.outputs.size());
for (const auto &i: req.outputs)
{
- // get tx_hash, tx_out_index from DB
- const output_data_t od = m_db->get_output_key(i.amount, i.index);
- tx_out_index toi = m_db->get_output_tx_and_index(i.amount, i.index);
- bool unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first));
+ amounts.push_back(i.amount);
+ offsets.push_back(i.index);
+ }
+ m_db->get_output_key(epee::span<const uint64_t>(amounts.data(), amounts.size()), offsets, data);
+ if (data.size() != req.outputs.size())
+ {
+ MERROR("Unexpected output data size: expected " << req.outputs.size() << ", got " << data.size());
+ return false;
+ }
+ for (const auto &t: data)
+ res.outs.push_back({t.pubkey, t.commitment, is_tx_spendtime_unlocked(t.unlock_time), t.height, crypto::null_hash});
- res.outs.push_back({od.pubkey, od.commitment, unlocked, od.height, toi.first});
+ if (req.get_txid)
+ {
+ for (size_t i = 0; i < req.outputs.size(); ++i)
+ {
+ tx_out_index toi = m_db->get_output_tx_and_index(req.outputs[i].amount, req.outputs[i].index);
+ res.outs[i].txid = toi.first;
+ }
}
}
catch (const std::exception &e)
@@ -1804,6 +1823,7 @@ bool Blockchain::get_output_distribution(uint64_t amount, uint64_t from_height,
case STAGENET: start_height = stagenet_hard_forks[3].height; break;
case TESTNET: start_height = testnet_hard_forks[3].height; break;
case MAINNET: start_height = mainnet_hard_forks[3].height; break;
+ case FAKECHAIN: start_height = 0; break;
default: return false;
}
}
@@ -1822,18 +1842,21 @@ bool Blockchain::get_output_distribution(uint64_t amount, uint64_t from_height,
uint64_t db_height = m_db->height();
if (db_height == 0)
return false;
- if (to_height == 0)
- to_height = db_height - 1;
if (start_height >= db_height || to_height >= db_height)
return false;
if (amount == 0)
{
std::vector<uint64_t> heights;
heights.reserve(to_height + 1 - start_height);
- for (uint64_t h = start_height; h <= to_height; ++h)
+ uint64_t real_start_height = start_height > 0 ? start_height-1 : start_height;
+ for (uint64_t h = real_start_height; h <= to_height; ++h)
heights.push_back(h);
distribution = m_db->get_block_cumulative_rct_outputs(heights);
- base = 0;
+ if (start_height > 0)
+ {
+ base = distribution[0];
+ distribution.erase(distribution.begin());
+ }
return true;
}
else
@@ -3786,12 +3809,11 @@ bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync)
}
//------------------------------------------------------------------
-//FIXME: unused parameter txs
-void Blockchain::output_scan_worker(const uint64_t amount, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs, std::unordered_map<crypto::hash, cryptonote::transaction> &txs) const
+void Blockchain::output_scan_worker(const uint64_t amount, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs) const
{
try
{
- m_db->get_output_key(amount, offsets, outputs, true);
+ m_db->get_output_key(epee::span<const uint64_t>(&amount, 1), offsets, outputs, true);
}
catch (const std::exception& e)
{
@@ -4164,21 +4186,19 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
offsets.second.erase(last, offsets.second.end());
}
- // [output] stores all transactions for each tx_out_index::hash found
- std::vector<std::unordered_map<crypto::hash, cryptonote::transaction>> transactions(amounts.size());
-
+ // gather all the output keys
threads = tpool.get_max_concurrency();
if (!m_db->can_thread_bulk_indices())
threads = 1;
- if (threads > 1)
+ if (threads > 1 && amounts.size() > 1)
{
tools::threadpool::waiter waiter;
for (size_t i = 0; i < amounts.size(); i++)
{
uint64_t amount = amounts[i];
- tpool.submit(&waiter, boost::bind(&Blockchain::output_scan_worker, this, amount, std::cref(offset_map[amount]), std::ref(tx_map[amount]), std::ref(transactions[i])), true);
+ tpool.submit(&waiter, boost::bind(&Blockchain::output_scan_worker, this, amount, std::cref(offset_map[amount]), std::ref(tx_map[amount])), true);
}
waiter.wait(&tpool);
}
@@ -4187,7 +4207,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
for (size_t i = 0; i < amounts.size(); i++)
{
uint64_t amount = amounts[i];
- output_scan_worker(amount, offset_map[amount], tx_map[amount], transactions[i]);
+ output_scan_worker(amount, offset_map[amount], tx_map[amount]);
}
}
@@ -4254,9 +4274,9 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::vector<block_complete
return true;
}
-void Blockchain::add_txpool_tx(transaction &tx, const txpool_tx_meta_t &meta)
+void Blockchain::add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &meta)
{
- m_db->add_txpool_tx(tx, meta);
+ m_db->add_txpool_tx(txid, blob, meta);
}
void Blockchain::update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &meta)
diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h
index f140d7719..dfe833fb4 100644
--- a/src/cryptonote_core/blockchain.h
+++ b/src/cryptonote_core/blockchain.h
@@ -916,11 +916,9 @@ namespace cryptonote
* @param amount the amount
* @param offsets the indices (indexed to the amount) of the outputs
* @param outputs return-by-reference the outputs collected
- * @param txs unused, candidate for removal
*/
void output_scan_worker(const uint64_t amount,const std::vector<uint64_t> &offsets,
- std::vector<output_data_t> &outputs, std::unordered_map<crypto::hash,
- cryptonote::transaction> &txs) const;
+ std::vector<output_data_t> &outputs) const;
/**
* @brief computes the "short" and "long" hashes for a set of blocks
@@ -939,7 +937,7 @@ namespace cryptonote
*/
std::list<std::pair<block_extended_info,std::vector<crypto::hash>>> get_alternative_chains() const;
- void add_txpool_tx(transaction &tx, const txpool_tx_meta_t &meta);
+ void add_txpool_tx(const crypto::hash &txid, const cryptonote::blobdata &blob, const txpool_tx_meta_t &meta);
void update_txpool_tx(const crypto::hash &txid, const txpool_tx_meta_t &meta);
void remove_txpool_tx(const crypto::hash &txid);
uint64_t get_txpool_tx_count(bool include_unrelayed_txes = true) const;
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 00537e8b7..b353cc5d1 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -906,7 +906,7 @@ namespace cryptonote
}
const size_t weight = get_transaction_weight(results[i].tx, it->size());
- ok &= add_new_tx(results[i].tx, results[i].hash, results[i].prefix_hash, weight, tvc[i], keeped_by_block, relayed, do_not_relay);
+ ok &= add_new_tx(results[i].tx, results[i].hash, tx_blobs[i], results[i].prefix_hash, weight, tvc[i], keeped_by_block, relayed, do_not_relay);
if(tvc[i].m_verifivation_failed)
{MERROR_VER("Transaction verification failed: " << results[i].hash);}
else if(tvc[i].m_verifivation_impossible)
@@ -1124,7 +1124,7 @@ namespace cryptonote
blobdata bl;
t_serializable_object_to_blob(tx, bl);
size_t tx_weight = get_transaction_weight(tx, bl.size());
- return add_new_tx(tx, tx_hash, tx_prefix_hash, tx_weight, tvc, keeped_by_block, relayed, do_not_relay);
+ return add_new_tx(tx, tx_hash, bl, tx_prefix_hash, tx_weight, tvc, keeped_by_block, relayed, do_not_relay);
}
//-----------------------------------------------------------------------------------------------
size_t core::get_blockchain_total_transactions() const
@@ -1132,7 +1132,7 @@ namespace cryptonote
return m_blockchain_storage.get_total_transactions();
}
//-----------------------------------------------------------------------------------------------
- bool core::add_new_tx(transaction& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prefix_hash, size_t tx_weight, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
+ bool core::add_new_tx(transaction& tx, const crypto::hash& tx_hash, const cryptonote::blobdata &blob, const crypto::hash& tx_prefix_hash, size_t tx_weight, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay)
{
if (keeped_by_block)
get_blockchain_storage().on_new_tx_from_block(tx);
@@ -1150,7 +1150,7 @@ namespace cryptonote
}
uint8_t version = m_blockchain_storage.get_current_hard_fork_version();
- return m_mempool.add_tx(tx, tx_hash, tx_weight, tvc, keeped_by_block, relayed, do_not_relay, version);
+ return m_mempool.add_tx(tx, tx_hash, blob, tx_weight, tvc, keeped_by_block, relayed, do_not_relay, version);
}
//-----------------------------------------------------------------------------------------------
bool core::relay_txpool_transactions()
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 7ddba77b2..46c3c3e8b 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -782,13 +782,14 @@ namespace cryptonote
* @copydoc add_new_tx(transaction&, tx_verification_context&, bool)
*
* @param tx_hash the transaction's hash
+ * @param blob the transaction as a blob
* @param tx_prefix_hash the transaction prefix' hash
* @param tx_weight the weight of the transaction
* @param relayed whether or not the transaction was relayed to us
* @param do_not_relay whether to prevent the transaction from being relayed
*
*/
- bool add_new_tx(transaction& tx, const crypto::hash& tx_hash, const crypto::hash& tx_prefix_hash, size_t tx_weight, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay);
+ bool add_new_tx(transaction& tx, const crypto::hash& tx_hash, const cryptonote::blobdata &blob, const crypto::hash& tx_prefix_hash, size_t tx_weight, tx_verification_context& tvc, bool keeped_by_block, bool relayed, bool do_not_relay);
/**
* @brief add a new transaction to the transaction pool
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index 70f7e8328..e2900916b 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -111,7 +111,7 @@ namespace cryptonote
}
//---------------------------------------------------------------------------------
- bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, size_t tx_weight, tx_verification_context& tvc, bool kept_by_block, bool relayed, bool do_not_relay, uint8_t version)
+ bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context& tvc, bool kept_by_block, bool relayed, bool do_not_relay, uint8_t version)
{
// this should already be called with that lock, but let's make it explicit for clarity
CRITICAL_REGION_LOCAL(m_transactions_lock);
@@ -247,9 +247,11 @@ namespace cryptonote
memset(meta.padding, 0, sizeof(meta.padding));
try
{
+ if (kept_by_block)
+ m_parsed_tx_cache.insert(std::make_pair(id, tx));
CRITICAL_REGION_LOCAL1(m_blockchain);
LockedTXN lock(m_blockchain);
- m_blockchain.add_txpool_tx(tx, meta);
+ m_blockchain.add_txpool_tx(id, blob, meta);
if (!insert_key_images(tx, id, kept_by_block))
return false;
m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id);
@@ -288,12 +290,13 @@ namespace cryptonote
try
{
+ if (kept_by_block)
+ m_parsed_tx_cache.insert(std::make_pair(id, tx));
CRITICAL_REGION_LOCAL1(m_blockchain);
LockedTXN lock(m_blockchain);
- const crypto::hash txid = get_transaction_hash(tx);
- m_blockchain.remove_txpool_tx(txid);
- m_blockchain.add_txpool_tx(tx, meta);
- if (!insert_key_images(tx, txid, kept_by_block))
+ m_blockchain.remove_txpool_tx(id);
+ m_blockchain.add_txpool_tx(id, blob, meta);
+ if (!insert_key_images(tx, id, kept_by_block))
return false;
m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id);
}
@@ -324,9 +327,11 @@ namespace cryptonote
{
crypto::hash h = null_hash;
size_t blob_size = 0;
- if (!get_transaction_hash(tx, h, blob_size) || blob_size == 0)
+ cryptonote::blobdata bl;
+ t_serializable_object_to_blob(tx, bl);
+ if (bl.size() == 0 || !get_transaction_hash(tx, h))
return false;
- return add_tx(tx, h, get_transaction_weight(tx, blob_size), tvc, keeped_by_block, relayed, do_not_relay, version);
+ return add_tx(tx, h, bl, get_transaction_weight(tx, bl.size()), tvc, keeped_by_block, relayed, do_not_relay, version);
}
//---------------------------------------------------------------------------------
size_t tx_memory_pool::get_txpool_weight() const
@@ -454,8 +459,6 @@ namespace cryptonote
CRITICAL_REGION_LOCAL1(m_blockchain);
auto sorted_it = find_tx_in_sorted_container(id);
- if (sorted_it == m_txs_by_fee_and_receive_time.end())
- return false;
try
{
@@ -467,7 +470,12 @@ namespace cryptonote
return false;
}
cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(id);
- if (!parse_and_validate_tx_from_blob(txblob, tx))
+ auto ci = m_parsed_tx_cache.find(id);
+ if (ci != m_parsed_tx_cache.end())
+ {
+ tx = ci->second;
+ }
+ else if (!parse_and_validate_tx_from_blob(txblob, tx))
{
MERROR("Failed to parse tx from txpool");
return false;
@@ -489,7 +497,8 @@ namespace cryptonote
return false;
}
- m_txs_by_fee_and_receive_time.erase(sorted_it);
+ if (sorted_it != m_txs_by_fee_and_receive_time.end())
+ m_txs_by_fee_and_receive_time.erase(sorted_it);
++m_cookie;
return true;
}
@@ -910,6 +919,7 @@ namespace cryptonote
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
m_input_cache.clear();
+ m_parsed_tx_cache.clear();
return true;
}
//---------------------------------------------------------------------------------
@@ -917,6 +927,7 @@ namespace cryptonote
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
m_input_cache.clear();
+ m_parsed_tx_cache.clear();
return true;
}
//---------------------------------------------------------------------------------
diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h
index 7a0cc23bf..670d70d77 100644
--- a/src/cryptonote_core/tx_pool.h
+++ b/src/cryptonote_core/tx_pool.h
@@ -107,7 +107,7 @@ namespace cryptonote
* @param id the transaction's hash
* @param tx_weight the transaction's weight
*/
- bool add_tx(transaction &tx, const crypto::hash &id, size_t tx_weight, tx_verification_context& tvc, bool kept_by_block, bool relayed, bool do_not_relay, uint8_t version);
+ bool add_tx(transaction &tx, const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context& tvc, bool kept_by_block, bool relayed, bool do_not_relay, uint8_t version);
/**
* @brief add a transaction to the transaction pool
@@ -510,7 +510,7 @@ namespace cryptonote
* @param txd the transaction to check (and info about it)
* @param txid the txid of the transaction to check
* @param txblob the transaction blob to check
- * @param tx the parsed transaction prefix, if successful
+ * @param tx the parsed transaction, if successful
*
* @return true if the transaction is good to go, otherwise false
*/
@@ -584,6 +584,8 @@ private:
size_t m_txpool_weight;
mutable std::unordered_map<crypto::hash, std::tuple<bool, tx_verification_context, uint64_t, crypto::hash>> m_input_cache;
+
+ std::unordered_map<crypto::hash, transaction> m_parsed_tx_cache;
};
}