aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_core/blockchain.cpp
diff options
context:
space:
mode:
authormoneromooo-monero <moneromooo-monero@users.noreply.github.com>2016-04-17 11:04:01 +0100
committermoneromooo-monero <moneromooo-monero@users.noreply.github.com>2018-08-16 12:44:33 +0000
commit82d1b74500aa7ffab47f428f9ca26bb43cc2d8af (patch)
tree4bf2f0630275fc66125c0db19853ce32aca12ac7 /src/cryptonote_core/blockchain.cpp
parentMerge pull request #4191 (diff)
downloadmonero-82d1b74500aa7ffab47f428f9ca26bb43cc2d8af.tar.xz
core: cache block template where possible
This avoids constant rechecking of the same things each time a miner asks for the block template. The tx pool maintains a cookie to allow users to detect when the pool state changed, which means the block template needs rebuilding.
Diffstat (limited to 'src/cryptonote_core/blockchain.cpp')
-rw-r--r--src/cryptonote_core/blockchain.cpp44
1 files changed, 43 insertions, 1 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 87ef47c11..4f1b028a1 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -158,7 +158,8 @@ Blockchain::Blockchain(tx_memory_pool& tx_pool) :
m_db(), m_tx_pool(tx_pool), m_hardfork(NULL), m_timestamps_and_difficulties_height(0), m_current_block_cumul_sz_limit(0), m_current_block_cumul_sz_median(0),
m_enforce_dns_checkpoints(false), m_max_prepare_blocks_threads(4), m_db_blocks_per_sync(1), m_db_sync_mode(db_async), m_db_default_sync(false), m_fast_sync(true), m_show_time_stats(false), m_sync_counter(0), m_cancel(false),
m_difficulty_for_next_block_top_hash(crypto::null_hash),
- m_difficulty_for_next_block(1)
+ m_difficulty_for_next_block(1),
+ m_btc_valid(false)
{
LOG_PRINT_L3("Blockchain::" << __func__);
}
@@ -632,6 +633,7 @@ block Blockchain::pop_block_from_blockchain()
update_next_cumulative_size_limit();
m_tx_pool.on_blockchain_dec(m_db->height()-1, get_tail_id());
+ invalidate_block_template_cache();
return popped_block;
}
@@ -642,6 +644,7 @@ bool Blockchain::reset_and_set_genesis_block(const block& b)
CRITICAL_REGION_LOCAL(m_blockchain_lock);
m_timestamps_and_difficulties_height = 0;
m_alternative_chains.clear();
+ invalidate_block_template_cache();
m_db->reset();
m_hardfork->init();
@@ -1212,9 +1215,26 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
LOG_PRINT_L3("Blockchain::" << __func__);
size_t median_size;
uint64_t already_generated_coins;
+ uint64_t pool_cookie;
CRITICAL_REGION_BEGIN(m_blockchain_lock);
height = m_db->height();
+ if (m_btc_valid) {
+ // The pool cookie is atomic. The lack of locking is OK, as if it changes
+ // just as we compare it, we'll just use a slightly old template, but
+ // this would be the case anyway if we'd lock, and the change happened
+ // just after the block template was created
+ if (!memcmp(&miner_address, &m_btc_address, sizeof(cryptonote::account_public_address)) && m_btc_nonce == ex_nonce && m_btc_pool_cookie == m_tx_pool.cookie()) {
+ MDEBUG("Using cached template");
+ m_btc.timestamp = time(NULL); // update timestamp unconditionally
+ b = m_btc;
+ diffic = m_btc_difficulty;
+ expected_reward = m_btc_expected_reward;
+ return true;
+ }
+ MDEBUG("Not using cached template: address " << (!memcmp(&miner_address, &m_btc_address, sizeof(cryptonote::account_public_address))) << ", nonce " << (m_btc_nonce == ex_nonce) << ", cookie " << (m_btc_pool_cookie == m_tx_pool.cookie()));
+ invalidate_block_template_cache();
+ }
b.major_version = m_hardfork->get_current_version();
b.minor_version = m_hardfork->get_ideal_version();
@@ -1241,6 +1261,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
{
return false;
}
+ pool_cookie = m_tx_pool.cookie();
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
size_t real_txs_size = 0;
uint64_t real_fee = 0;
@@ -1355,6 +1376,8 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
MDEBUG("Creating block template: miner tx size " << coinbase_blob_size <<
", cumulative size " << cumulative_size << " is now good");
#endif
+
+ cache_block_template(b, miner_address, ex_nonce, diffic, expected_reward, pool_cookie);
return true;
}
LOG_ERROR("Failed to create_block_template with " << 10 << " tries");
@@ -3697,6 +3720,7 @@ leave:
// appears to be a NOP *and* is called elsewhere. wat?
m_tx_pool.on_blockchain_inc(new_height, id);
get_difficulty_for_next_block(); // just to cache it
+ invalidate_block_template_cache();
return true;
}
@@ -4666,6 +4690,24 @@ bool Blockchain::for_all_outputs(uint64_t amount, std::function<bool(uint64_t he
return m_db->for_all_outputs(amount, f);;
}
+void Blockchain::invalidate_block_template_cache()
+{
+ MDEBUG("Invalidating block template cache");
+ m_btc_valid = false;
+}
+
+void Blockchain::cache_block_template(const block &b, const cryptonote::account_public_address &address, const blobdata &nonce, const difficulty_type &diff, uint64_t expected_reward, uint64_t pool_cookie)
+{
+ MDEBUG("Setting block template cache");
+ m_btc = b;
+ m_btc_address = address;
+ m_btc_nonce = nonce;
+ m_btc_difficulty = diff;
+ m_btc_expected_reward = expected_reward;
+ m_btc_pool_cookie = pool_cookie;
+ m_btc_valid = true;
+}
+
namespace cryptonote {
template bool Blockchain::get_transactions(const std::vector<crypto::hash>&, std::vector<transaction>&, std::vector<crypto::hash>&) const;
template bool Blockchain::get_transactions_blobs(const std::vector<crypto::hash>&, std::vector<cryptonote::blobdata>&, std::vector<crypto::hash>&, bool) const;