mirror of
https://github.com/SChernykh/p2pool.git
synced 2025-01-09 12:19:26 +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;
|
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"
|
// Collect shares from each block in the PPLNS window, starting from the "tip"
|
||||||
|
|
||||||
uint64_t block_depth = 0;
|
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;
|
const difficulty_type max_pplns_weight = (sidechain_version > 1) ? (mainchain_diff * 2) : diff_max;
|
||||||
difficulty_type pplns_weight;
|
difficulty_type pplns_weight;
|
||||||
|
|
||||||
|
unordered_set<MinerShare> shares_set;
|
||||||
|
shares_set.reserve(m_chainWindowSize * 2);
|
||||||
|
|
||||||
do {
|
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) {
|
for (const hash& uncle_id : cur->m_uncles) {
|
||||||
auto it = m_blocksById.find(uncle_id);
|
auto it = m_blocksById.find(uncle_id);
|
||||||
|
@ -391,15 +391,21 @@ bool SideChain::get_shares(const PoolBlock* tip, std::vector<MinerShare>& shares
|
||||||
continue;
|
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;
|
pplns_weight = new_pplns_weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Always add non-uncle shares even if PPLNS weight goes above the limit
|
// Always add non-uncle shares even if PPLNS weight goes above the limit
|
||||||
shares.push_back(cur_share);
|
auto result = shares_set.emplace(cur_weight, &cur->m_minerWallet);
|
||||||
pplns_weight += cur_share.m_weight;
|
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
|
// 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) {
|
if (pplns_weight > max_pplns_weight) {
|
||||||
|
@ -426,34 +432,27 @@ bool SideChain::get_shares(const PoolBlock* tip, std::vector<MinerShare>& shares
|
||||||
cur = it->second;
|
cur = it->second;
|
||||||
} while (true);
|
} 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; });
|
std::sort(shares.begin(), shares.end(), [](const auto& a, const auto& b) { return *a.m_wallet < *b.m_wallet; });
|
||||||
|
|
||||||
size_t k = 0;
|
const uint64_t n = shares.size();
|
||||||
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");
|
|
||||||
|
|
||||||
// Shuffle shares
|
// Shuffle shares
|
||||||
if (sidechain_version > 1) {
|
if ((sidechain_version > 1) && (n > 1)) {
|
||||||
std::mt19937_64 rng(*reinterpret_cast<const uint64_t*>(tip->m_txkeySecSeed.h));
|
hash h;
|
||||||
|
keccak(tip->m_txkeySecSeed.h, HASH_SIZE, h.h);
|
||||||
|
|
||||||
for (int64_t i = k; i > 0; --i) {
|
uint64_t seed = *reinterpret_cast<uint64_t*>(h.h);
|
||||||
std::swap(shares[i], shares[rng() % (i + 1)]);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,8 @@ struct MinerShare
|
||||||
FORCEINLINE MinerShare() : m_weight(), m_wallet(nullptr) {}
|
FORCEINLINE MinerShare() : m_weight(), m_wallet(nullptr) {}
|
||||||
FORCEINLINE MinerShare(const difficulty_type& w, const Wallet* x) : m_weight(w), m_wallet(x) {}
|
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;
|
difficulty_type m_weight;
|
||||||
const Wallet* m_wallet;
|
const Wallet* m_wallet;
|
||||||
};
|
};
|
||||||
|
@ -157,3 +159,16 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace p2pool
|
} // 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;
|
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()
|
FORCEINLINE uint64_t seconds_since_epoch()
|
||||||
{
|
{
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
Loading…
Reference in a new issue