mirror of
https://github.com/SChernykh/p2pool.git
synced 2025-01-09 04:09:29 +00:00
Optimized get_shares
This commit is contained in:
parent
850eb8e6e0
commit
4f2ad9a93c
3 changed files with 50 additions and 28 deletions
|
@ -335,9 +335,6 @@ bool SideChain::get_shares(const PoolBlock* tip, std::vector<MinerShare>& shares
|
|||
|
||||
const int L = quiet ? 6 : 3;
|
||||
|
||||
shares.clear();
|
||||
shares.reserve(m_chainWindowSize * 2);
|
||||
|
||||
// Collect shares from each block in the PPLNS window, starting from the "tip"
|
||||
|
||||
uint64_t block_depth = 0;
|
||||
|
@ -363,8 +360,11 @@ bool SideChain::get_shares(const PoolBlock* tip, std::vector<MinerShare>& shares
|
|||
const difficulty_type max_pplns_weight = (sidechain_version > 1) ? (mainchain_diff * 2) : diff_max;
|
||||
difficulty_type pplns_weight;
|
||||
|
||||
unordered_set<MinerShare> shares_set;
|
||||
shares_set.reserve(m_chainWindowSize * 2);
|
||||
|
||||
do {
|
||||
MinerShare cur_share{ cur->m_difficulty, &cur->m_minerWallet };
|
||||
difficulty_type cur_weight = cur->m_difficulty;
|
||||
|
||||
for (const hash& uncle_id : cur->m_uncles) {
|
||||
auto it = m_blocksById.find(uncle_id);
|
||||
|
@ -391,15 +391,21 @@ bool SideChain::get_shares(const PoolBlock* tip, std::vector<MinerShare>& shares
|
|||
continue;
|
||||
}
|
||||
|
||||
cur_share.m_weight += uncle_penalty;
|
||||
cur_weight += uncle_penalty;
|
||||
|
||||
shares.emplace_back(uncle_weight, &uncle->m_minerWallet);
|
||||
auto result = shares_set.emplace(uncle_weight, &uncle->m_minerWallet);
|
||||
if (!result.second) {
|
||||
result.first->m_weight += uncle_weight;
|
||||
}
|
||||
pplns_weight = new_pplns_weight;
|
||||
}
|
||||
|
||||
// Always add non-uncle shares even if PPLNS weight goes above the limit
|
||||
shares.push_back(cur_share);
|
||||
pplns_weight += cur_share.m_weight;
|
||||
auto result = shares_set.emplace(cur_weight, &cur->m_minerWallet);
|
||||
if (!result.second) {
|
||||
result.first->m_weight += cur_weight;
|
||||
}
|
||||
pplns_weight += cur_weight;
|
||||
|
||||
// One non-uncle share can go above the limit, but it will also guarantee that "shares" is never empty
|
||||
if (pplns_weight > max_pplns_weight) {
|
||||
|
@ -426,34 +432,27 @@ bool SideChain::get_shares(const PoolBlock* tip, std::vector<MinerShare>& shares
|
|||
cur = it->second;
|
||||
} while (true);
|
||||
|
||||
// Combine shares with the same wallet addresses
|
||||
shares.assign(shares_set.begin(), shares_set.end());
|
||||
std::sort(shares.begin(), shares.end(), [](const auto& a, const auto& b) { return *a.m_wallet < *b.m_wallet; });
|
||||
|
||||
size_t k = 0;
|
||||
for (size_t i = 1, n = shares.size(); i < n; ++i)
|
||||
{
|
||||
if (*shares[i].m_wallet == *shares[k].m_wallet) {
|
||||
shares[k].m_weight += shares[i].m_weight;
|
||||
}
|
||||
else {
|
||||
++k;
|
||||
shares[k].m_weight = shares[i].m_weight;
|
||||
shares[k].m_wallet = shares[i].m_wallet;
|
||||
}
|
||||
}
|
||||
|
||||
shares.resize(k + 1);
|
||||
LOGINFO(6, "get_shares: " << k + 1 << " unique wallets in PPLNS window");
|
||||
const uint64_t n = shares.size();
|
||||
|
||||
// Shuffle shares
|
||||
if (sidechain_version > 1) {
|
||||
std::mt19937_64 rng(*reinterpret_cast<const uint64_t*>(tip->m_txkeySecSeed.h));
|
||||
if ((sidechain_version > 1) && (n > 1)) {
|
||||
hash h;
|
||||
keccak(tip->m_txkeySecSeed.h, HASH_SIZE, h.h);
|
||||
|
||||
for (int64_t i = k; i > 0; --i) {
|
||||
std::swap(shares[i], shares[rng() % (i + 1)]);
|
||||
uint64_t seed = *reinterpret_cast<uint64_t*>(h.h);
|
||||
if (seed == 0) seed = 1;
|
||||
|
||||
for (uint64_t i = 0, k; i < n - 1; ++i) {
|
||||
seed = xorshift64star(seed);
|
||||
umul128(seed, n - i, &k);
|
||||
std::swap(shares[i], shares[i + k]);
|
||||
}
|
||||
}
|
||||
|
||||
LOGINFO(6, "get_shares: " << n << " unique wallets in PPLNS window");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -32,6 +32,8 @@ struct MinerShare
|
|||
FORCEINLINE MinerShare() : m_weight(), m_wallet(nullptr) {}
|
||||
FORCEINLINE MinerShare(const difficulty_type& w, const Wallet* x) : m_weight(w), m_wallet(x) {}
|
||||
|
||||
FORCEINLINE bool operator==(const MinerShare& s) const { return *m_wallet == *s.m_wallet; }
|
||||
|
||||
difficulty_type m_weight;
|
||||
const Wallet* m_wallet;
|
||||
};
|
||||
|
@ -157,3 +159,16 @@ private:
|
|||
};
|
||||
|
||||
} // namespace p2pool
|
||||
|
||||
namespace robin_hood {
|
||||
|
||||
template<>
|
||||
struct hash<p2pool::MinerShare>
|
||||
{
|
||||
FORCEINLINE size_t operator()(const p2pool::MinerShare& value) const noexcept
|
||||
{
|
||||
return hash_bytes(value.m_wallet->spend_public_key().h, p2pool::HASH_SIZE);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace robin_hood
|
||||
|
|
|
@ -208,6 +208,14 @@ struct RandomDeviceSeed
|
|||
static RandomDeviceSeed instance;
|
||||
};
|
||||
|
||||
FORCEINLINE uint64_t xorshift64star(uint64_t x)
|
||||
{
|
||||
x ^= x >> 12;
|
||||
x ^= x << 25;
|
||||
x ^= x >> 27;
|
||||
return x * 0x2545F4914F6CDD1DULL;
|
||||
}
|
||||
|
||||
FORCEINLINE uint64_t seconds_since_epoch()
|
||||
{
|
||||
using namespace std::chrono;
|
||||
|
|
Loading…
Reference in a new issue