diff --git a/src/crypto.cpp b/src/crypto.cpp index e253b24..ce7e7fe 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -214,10 +214,11 @@ public: derive_view_tag(derivation, output_index, view_tag); + const uint64_t t = seconds_since_epoch(); { WriteLock lock(derivations_lock); - DerivationEntry& entry = derivations->emplace(index, DerivationEntry{ derivation, { 0xFFFFFFFFUL, 0xFFFFFFFFUL }, {} }).first->second; + DerivationEntry& entry = derivations->emplace(index, DerivationEntry{ derivation, { 0xFFFFFFFFUL, 0xFFFFFFFFUL }, {}, t }).first->second; entry.add_view_tag(static_cast(output_index << 8) | view_tag); } @@ -235,7 +236,7 @@ public: ReadLock lock(public_keys_lock); auto it = public_keys->find(index); if (it != public_keys->end()) { - derived_key = it->second; + derived_key = it->second.m_key; return true; } } @@ -258,9 +259,10 @@ public: ge_p1p1_to_p2(&point5, &point4); ge_tobytes(derived_key.h, &point5); + const uint64_t t = seconds_since_epoch(); { WriteLock lock(public_keys_lock); - public_keys->emplace(index, derived_key); + public_keys->emplace(index, PublicKeyEntry{ derived_key, t }); } return true; @@ -276,8 +278,8 @@ public: ReadLock lock(tx_keys_lock); auto it = tx_keys->find(index); if (it != tx_keys->end()) { - pub = it->second.first; - sec = it->second.second; + pub = it->second.m_pub; + sec = it->second.m_sec; return; } } @@ -292,14 +294,42 @@ public: generate_keys_deterministic(pub, sec, entropy, sizeof(entropy)); + const uint64_t t = seconds_since_epoch(); { WriteLock lock(tx_keys_lock); - tx_keys->emplace(index, std::pair(pub, sec)); + tx_keys->emplace(index, TxKeyEntry{ pub, sec, t }); } } - void clear() + void clear(uint64_t timestamp) { + if (timestamp) { + auto clean_old = [timestamp](auto* table) { + for (auto it = table->begin(); it != table->end();) { + if (it->second.m_timestamp < timestamp) { + it = table->erase(it); + } + else { + ++it; + } + } + }; + + { + WriteLock lock(derivations_lock); + clean_old(derivations); + } + { + WriteLock lock(public_keys_lock); + clean_old(public_keys); + } + { + WriteLock lock(tx_keys_lock); + clean_old(tx_keys); + } + return; + } + { WriteLock lock(derivations_lock); delete derivations; @@ -326,6 +356,7 @@ private: hash m_derivation; uint32_t m_viewTags1[2] = { 0xFFFFFFFFUL, 0xFFFFFFFFUL }; std::vector m_viewTags2; + uint64_t m_timestamp; FORCEINLINE bool find_view_tag(size_t output_index, uint8_t& view_tag) const { @@ -373,9 +404,22 @@ private: } }; + struct PublicKeyEntry + { + hash m_key; + uint64_t m_timestamp; + }; + + struct TxKeyEntry + { + hash m_pub; + hash m_sec; + uint64_t m_timestamp; + }; + typedef unordered_map, DerivationEntry> DerivationsMap; - typedef unordered_map, hash> PublicKeysMap; - typedef unordered_map, std::pair> TxKeysMap; + typedef unordered_map, PublicKeyEntry> PublicKeysMap; + typedef unordered_map, TxKeyEntry> TxKeysMap; uv_rwlock_t derivations_lock; DerivationsMap* derivations; @@ -435,10 +479,10 @@ void destroy_crypto_cache() } } -void clear_crypto_cache() +void clear_crypto_cache(uint64_t timestamp) { if (cache) { - cache->clear(); + cache->clear(timestamp); } } diff --git a/src/crypto.h b/src/crypto.h index ab5c6cd..0d7821c 100644 --- a/src/crypto.h +++ b/src/crypto.h @@ -29,6 +29,6 @@ void derive_view_tag(const hash& derivation, size_t output_index, uint8_t& view_ void init_crypto_cache(); void destroy_crypto_cache(); -void clear_crypto_cache(); +void clear_crypto_cache(uint64_t timestamp = 0); } // namespace p2pool diff --git a/src/p2pool.cpp b/src/p2pool.cpp index f2c7693..5a6849e 100644 --- a/src/p2pool.cpp +++ b/src/p2pool.cpp @@ -56,6 +56,7 @@ p2pool::p2pool(int argc, char* argv[]) , m_submitBlockData{} , m_zmqLastActive(0) , m_startTime(seconds_since_epoch()) + , m_lastMinerDataReceived(0) { LOGINFO(1, log::LightCyan() << VERSION); @@ -335,9 +336,12 @@ void p2pool::handle_miner_data(MinerData& data) // Tx secret keys from all miners change every block, so cache can be cleared here if (m_sideChain->precalcFinished()) { - clear_crypto_cache(); + // Clear all cache entries older than the previous miner data + clear_crypto_cache(m_lastMinerDataReceived); } + m_lastMinerDataReceived = seconds_since_epoch(); + if (!is_main_thread()) { update_block_template_async(); } diff --git a/src/p2pool.h b/src/p2pool.h index bfc1337..0c6bc31 100644 --- a/src/p2pool.h +++ b/src/p2pool.h @@ -211,6 +211,8 @@ private: hash m_getMinerDataHash; bool m_getMinerDataPending = false; + + std::atomic m_lastMinerDataReceived; }; } // namespace p2pool