diff --git a/.github/workflows/test-sync.yml b/.github/workflows/test-sync.yml index c5bf920d..7429733a 100644 --- a/.github/workflows/test-sync.yml +++ b/.github/workflows/test-sync.yml @@ -68,7 +68,7 @@ jobs: python ../tests/src/stratum_dummy.py 2 & python ../tests/src/stratum_dummy.py 3 & sudo sysctl vm.mmap_rnd_bits=28 - TSAN_OPTIONS="suppressions=../tests/src/tsan_sup.txt halt_on_error=1" ./p2pool --host xmr.support --rpc-port 18081 --zmq-port 18083 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6 + TSAN_OPTIONS="suppressions=../tests/src/tsan_sup.txt halt_on_error=1 history_size=4" ./p2pool --host xmr.support --rpc-port 18081 --zmq-port 18083 --host node.richfowler.net --rpc-port 18089 --zmq-port 18084 --wallet 44MnN1f3Eto8DZYUWuE5XZNUtE3vcRzt2j6PzqWpPau34e6Cf4fAxt6X2MBmrm6F9YMEiMNjN6W4Shn4pLcfNAja621jwyg --mini --out-peers 200 --data-api data --local-api --loglevel 6 - name: Check p2pool.log run: | diff --git a/src/block_cache.cpp b/src/block_cache.cpp index 1005bdfd..cf84d8cd 100644 --- a/src/block_cache.cpp +++ b/src/block_cache.cpp @@ -19,6 +19,7 @@ #include "block_cache.h" #include "pool_block.h" #include "p2p_server.h" +#include "side_chain.h" LOG_CATEGORY(BlockCache) diff --git a/src/pool_block.cpp b/src/pool_block.cpp index c05a7170..00998706 100644 --- a/src/pool_block.cpp +++ b/src/pool_block.cpp @@ -29,6 +29,14 @@ LOG_CATEGORY(PoolBlock) namespace p2pool { +uv_rwlock_t PoolBlock::s_precalculatedSharesLock; + +static struct PrecalculatedLockInit +{ + FORCEINLINE PrecalculatedLockInit() { uv_rwlock_init(&PoolBlock::s_precalculatedSharesLock); } + FORCEINLINE ~PrecalculatedLockInit() { uv_rwlock_destroy(&PoolBlock::s_precalculatedSharesLock); } +} precalculated_lock_init; + PoolBlock::PoolBlock() : m_majorVersion(0) , m_minorVersion(0) @@ -115,6 +123,10 @@ PoolBlock& PoolBlock::operator=(const PoolBlock& b) m_broadcasted = b.m_broadcasted; m_wantBroadcast = b.m_wantBroadcast; m_precalculated = b.m_precalculated; + { + WriteLock lock(s_precalculatedSharesLock); + m_precalculatedShares = b.m_precalculatedShares; + } m_localTimestamp = seconds_since_epoch(); m_receivedTimestamp = b.m_receivedTimestamp; @@ -302,6 +314,11 @@ void PoolBlock::reset_offchain_data() m_wantBroadcast = false; m_precalculated = false; + { + WriteLock lock(s_precalculatedSharesLock); + m_precalculatedShares.clear(); + m_precalculatedShares.shrink_to_fit(); + } m_localTimestamp = seconds_since_epoch(); m_receivedTimestamp = 0; diff --git a/src/pool_block.h b/src/pool_block.h index a614a1b2..44634f5b 100644 --- a/src/pool_block.h +++ b/src/pool_block.h @@ -32,6 +32,7 @@ static FORCEINLINE constexpr int pool_block_debug() { return POOL_BLOCK_DEBUG; } class RandomX_Hasher_Base; class SideChain; +struct MinerShare; /* * -------------------------------------------------- @@ -161,6 +162,9 @@ struct PoolBlock bool m_precalculated; + static uv_rwlock_t s_precalculatedSharesLock; + std::vector m_precalculatedShares; + uint64_t m_localTimestamp; uint64_t m_receivedTimestamp; diff --git a/src/side_chain.cpp b/src/side_chain.cpp index 041ae20d..896916a1 100644 --- a/src/side_chain.cpp +++ b/src/side_chain.cpp @@ -1677,7 +1677,13 @@ void SideChain::verify(PoolBlock* block) } std::vector shares; - if (!get_shares(block, shares)) { + + if (block->m_precalculated) { + WriteLock lock(PoolBlock::s_precalculatedSharesLock); + shares = std::move(block->m_precalculatedShares); + } + + if (shares.empty() && !get_shares(block, shares)) { block->m_invalid = true; return; } @@ -2345,10 +2351,13 @@ void SideChain::launch_precalc(const PoolBlock* block) std::vector shares; if (get_shares(b, shares, nullptr, true)) { b->m_precalculated = true; - PrecalcJob* job = new PrecalcJob{ b, std::move(shares) }; + { + WriteLock lock(PoolBlock::s_precalculatedSharesLock); + b->m_precalculatedShares = std::move(shares); + } { MutexLock lock2(m_precalcJobsMutex); - m_precalcJobs.push_back(job); + m_precalcJobs.push_back(b); uv_cond_signal(&m_precalcJobsCond); } } @@ -2358,9 +2367,12 @@ void SideChain::launch_precalc(const PoolBlock* block) void SideChain::precalc_worker() { + std::vector> wallets; + wallets.reserve(m_chainWindowSize); + do { - PrecalcJob* job; - size_t num_inputs; + const PoolBlock* job; + { MutexLock lock(m_precalcJobsMutex); @@ -2381,32 +2393,28 @@ void SideChain::precalc_worker() // Filter out duplicate inputs for get_eph_public_key() uint8_t t[HASH_SIZE * 2 + sizeof(size_t)]; - memcpy(t, job->b->m_txkeySec.h, HASH_SIZE); + memcpy(t, job->m_txkeySec.h, HASH_SIZE); + + wallets.clear(); - const size_t n = job->shares.size(); - num_inputs = n; + ReadLock lock2(PoolBlock::s_precalculatedSharesLock); + + const size_t n = job->m_precalculatedShares.size(); for (size_t i = 0; i < n; ++i) { - memcpy(t + HASH_SIZE, job->shares[i].m_wallet->view_public_key().h, HASH_SIZE); + memcpy(t + HASH_SIZE, job->m_precalculatedShares[i].m_wallet->view_public_key().h, HASH_SIZE); memcpy(t + HASH_SIZE * 2, &i, sizeof(i)); - if (!m_uniquePrecalcInputs->insert(robin_hood::hash_bytes(t, array_size(t))).second) { - job->shares[i].m_wallet = nullptr; - --num_inputs; + if (m_uniquePrecalcInputs->insert(robin_hood::hash_bytes(t, array_size(t))).second) { + wallets.emplace_back(i, job->m_precalculatedShares[i].m_wallet); } } } - if (num_inputs) { - for (size_t i = 0, n = job->shares.size(); i < n; ++i) { - if (job->shares[i].m_wallet) { - hash eph_public_key; - uint8_t view_tag; - job->shares[i].m_wallet->get_eph_public_key(job->b->m_txkeySec, i, eph_public_key, view_tag); - } - } + for (const std::pair& w : wallets) { + hash eph_public_key; + uint8_t view_tag; + w.second->get_eph_public_key(job->m_txkeySec, w.first, eph_public_key, view_tag); } - - delete job; } while (true); } @@ -2420,9 +2428,6 @@ void SideChain::finish_precalc() { { MutexLock lock(m_precalcJobsMutex); - for (PrecalcJob* job : m_precalcJobs) { - delete job; - } m_precalcJobs.clear(); m_precalcJobs.shrink_to_fit(); uv_cond_broadcast(&m_precalcJobsCond); diff --git a/src/side_chain.h b/src/side_chain.h index 7f3bd450..27988e44 100644 --- a/src/side_chain.h +++ b/src/side_chain.h @@ -147,16 +147,10 @@ class SideChain : public nocopy_nomove ChainMain m_watchBlock; hash m_watchBlockMerkleRoot; - struct PrecalcJob - { - const PoolBlock* b; - std::vector shares; - }; - uv_cond_t m_precalcJobsCond; uv_mutex_t m_precalcJobsMutex; - std::vector m_precalcJobs; + std::vector m_precalcJobs; std::vector m_precalcWorkers; unordered_set* m_uniquePrecalcInputs; diff --git a/tests/src/merkle_tests.cpp b/tests/src/merkle_tests.cpp index a41e8d74..906b7502 100644 --- a/tests/src/merkle_tests.cpp +++ b/tests/src/merkle_tests.cpp @@ -19,6 +19,7 @@ #include "keccak.h" #include "merkle.h" #include "pool_block.h" +#include "side_chain.h" #include "keccak.h" #include "gtest/gtest.h"