Skip to content

Commit

Permalink
Added more 128 bit calculations
Browse files Browse the repository at this point in the history
  • Loading branch information
SChernykh committed Nov 16, 2022
1 parent b3bce16 commit 488ed8e
Show file tree
Hide file tree
Showing 6 changed files with 317 additions and 51 deletions.
32 changes: 30 additions & 2 deletions src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,8 @@ constexpr uint8_t TX_EXTRA_MERGE_MINING_TAG = 3;
#ifdef _MSC_VER
#define umul128 _umul128
#define udiv128 _udiv128
FORCEINLINE uint64_t shiftleft128(uint64_t lo, uint64_t hi, uint64_t shift) { return __shiftleft128(lo, hi, static_cast<unsigned char>(shift)); }
FORCEINLINE uint64_t shiftright128(uint64_t lo, uint64_t hi, uint64_t shift) { return __shiftright128(lo, hi, static_cast<unsigned char>(shift)); }
#else
FORCEINLINE uint64_t umul128(uint64_t a, uint64_t b, uint64_t* hi)
{
Expand All @@ -126,6 +128,9 @@ FORCEINLINE uint64_t udiv128(uint64_t hi, uint64_t lo, uint64_t divisor, uint64_

return result;
}

FORCEINLINE uint64_t shiftleft128(uint64_t lo, uint64_t hi, uint64_t shift) { return (hi << shift) | (lo >> (64 - shift)); }
FORCEINLINE uint64_t shiftright128(uint64_t lo, uint64_t hi, uint64_t shift) { return (hi << (64 - shift)) | (lo >> shift); }
#endif

template<typename T> constexpr FORCEINLINE T round_up(T a, size_t granularity) { return static_cast<T>(((a + (granularity - static_cast<size_t>(1))) / granularity) * granularity); }
Expand Down Expand Up @@ -197,6 +202,8 @@ struct difficulty_type
return *this;
}

FORCEINLINE difficulty_type& operator+=(uint64_t b) { return operator+=(difficulty_type{ b, 0 }); }

FORCEINLINE difficulty_type& operator-=(const difficulty_type& b)
{
#ifdef _MSC_VER
Expand All @@ -212,6 +219,8 @@ struct difficulty_type
return *this;
}

FORCEINLINE difficulty_type& operator-=(uint64_t b) { return operator-=(difficulty_type{ b, 0 }); }

FORCEINLINE difficulty_type& operator*=(const uint64_t b)
{
uint64_t t;
Expand All @@ -232,6 +241,8 @@ struct difficulty_type
return *this;
}

difficulty_type& operator/=(difficulty_type b);

FORCEINLINE bool operator<(const difficulty_type& other) const
{
if (hi < other.hi) return true;
Expand Down Expand Up @@ -279,20 +290,37 @@ struct difficulty_type
static_assert(sizeof(difficulty_type) == sizeof(uint64_t) * 2, "struct difficulty_type has invalid size, check your compiler options");
static_assert(std::is_standard_layout<difficulty_type>::value, "struct difficulty_type is not a POD, check your compiler options");

FORCEINLINE difficulty_type operator+(const difficulty_type& a, const difficulty_type& b)
template<typename T>
FORCEINLINE difficulty_type operator+(const difficulty_type& a, const T& b)
{
difficulty_type result = a;
result += b;
return result;
}

FORCEINLINE difficulty_type operator-(const difficulty_type& a, const difficulty_type& b)
template<typename T>
FORCEINLINE difficulty_type operator-(const difficulty_type& a, const T& b)
{
difficulty_type result = a;
result -= b;
return result;
}

FORCEINLINE difficulty_type operator*(const difficulty_type& a, uint64_t b)
{
difficulty_type result = a;
result *= b;
return result;
}

template<typename T>
FORCEINLINE difficulty_type operator/(const difficulty_type& a, const T& b)
{
difficulty_type result = a;
result /= b;
return result;
}

struct TxMempoolData
{
FORCEINLINE TxMempoolData() : id(), blob_size(0), weight(0), fee(0), time_received(0) {}
Expand Down
8 changes: 4 additions & 4 deletions src/log.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,6 @@ class Worker

// Create default loop here
uv_default_loop();
init_uv_threadpool();

uv_cond_init(&m_cond);
uv_mutex_init(&m_mutex);
Expand Down Expand Up @@ -92,6 +91,8 @@ class Worker
if (!m_logFile.is_open()) {
LOGERR(0, "failed to open " << log_file_name);
}

init_uv_threadpool();
}

~Worker()
Expand Down Expand Up @@ -160,7 +161,6 @@ class Worker
#endif

const uint32_t N = std::max(std::min(std::thread::hardware_concurrency(), 4U), 8U);
LOGINFO(4, "running " << N << " threads in the UV thread pool");

char buf[40] = {};
log::Stream s(buf);
Expand All @@ -169,13 +169,13 @@ class Worker
int err = putenv(buf);
if (err != 0) {
err = errno;
LOGWARN(1, "Couldn't set UV thread pool size to " << N << " threads, putenv returned error " << err);
LOGWARN(0, "Couldn't set UV thread pool size to " << N << " threads, putenv returned error " << err);
}

static uv_work_t dummy;
err = uv_queue_work(uv_default_loop_checked(), &dummy, [](uv_work_t*) {}, nullptr);
if (err) {
LOGERR(1, "init_uv_threadpool: uv_queue_work failed, error " << uv_err_name(err));
LOGERR(0, "init_uv_threadpool: uv_queue_work failed, error " << uv_err_name(err));
}
}

Expand Down
31 changes: 10 additions & 21 deletions src/side_chain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -325,7 +325,7 @@ bool SideChain::get_shares(const PoolBlock* tip, std::vector<MinerShare>& shares
uint64_t block_depth = 0;
const PoolBlock* cur = tip;
do {
MinerShare cur_share{ cur->m_difficulty.lo, &cur->m_minerWallet };
MinerShare cur_share{ cur->m_difficulty, &cur->m_minerWallet };

for (const hash& uncle_id : cur->m_uncles) {
auto it = m_blocksById.find(uncle_id);
Expand All @@ -343,14 +343,9 @@ bool SideChain::get_shares(const PoolBlock* tip, std::vector<MinerShare>& shares
}

// Take some % of uncle's weight into this share
uint64_t product[2];
product[0] = umul128(uncle->m_difficulty.lo, m_unclePenalty, &product[1]);

uint64_t rem;
const uint64_t uncle_penalty = udiv128(product[1], product[0], 100, &rem);

const difficulty_type uncle_penalty = uncle->m_difficulty * m_unclePenalty / 100;
cur_share.m_weight += uncle_penalty;
shares.emplace_back(uncle->m_difficulty.lo - uncle_penalty, &uncle->m_minerWallet);
shares.emplace_back(uncle->m_difficulty - uncle_penalty, &uncle->m_minerWallet);
}

shares.push_back(cur_share);
Expand Down Expand Up @@ -1092,9 +1087,9 @@ bool SideChain::split_reward(uint64_t reward, const std::vector<MinerShare>& sha
{
const size_t num_shares = shares.size();

const uint64_t total_weight = std::accumulate(shares.begin(), shares.end(), 0ULL, [](uint64_t a, const MinerShare& b) { return a + b.m_weight; });
const difficulty_type total_weight = std::accumulate(shares.begin(), shares.end(), difficulty_type(), [](const difficulty_type& a, const MinerShare& b) { return a + b.m_weight; });

if (total_weight == 0) {
if (total_weight.empty()) {
LOGERR(1, "total_weight is 0. Check the code!");
return false;
}
Expand All @@ -1103,18 +1098,14 @@ bool SideChain::split_reward(uint64_t reward, const std::vector<MinerShare>& sha
rewards.reserve(num_shares);

// Each miner gets a proportional fraction of the block reward
uint64_t w = 0;
difficulty_type w;
uint64_t reward_given = 0;
for (uint64_t i = 0; i < num_shares; ++i) {
w += shares[i].m_weight;

uint64_t hi;
const uint64_t lo = umul128(w, reward, &hi);

uint64_t rem;
const uint64_t next_value = udiv128(hi, lo, total_weight, &rem);
rewards.emplace_back(next_value - reward_given);
reward_given = next_value;
const difficulty_type next_value = w * reward / total_weight;
rewards.emplace_back(next_value.lo - reward_given);
reward_given = next_value.lo;
}

// Double check that we gave out the exact amount
Expand Down Expand Up @@ -1209,9 +1200,7 @@ bool SideChain::get_difficulty(const PoolBlock* tip, std::vector<DifficultyData>
}
}

curDifficulty = diff2 - diff1;
curDifficulty *= m_targetBlockTime;
curDifficulty /= delta_t;
curDifficulty = (diff2 - diff1) * m_targetBlockTime / delta_t;

if (curDifficulty < m_minDifficulty) {
curDifficulty = m_minDifficulty;
Expand Down
6 changes: 3 additions & 3 deletions src/side_chain.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ class P2PServer;

struct MinerShare
{
FORCEINLINE MinerShare() : m_weight(0), m_wallet(nullptr) {}
FORCEINLINE MinerShare(uint64_t w, const Wallet* x) : m_weight(w), m_wallet(x) {}
FORCEINLINE MinerShare() : m_weight(), m_wallet(nullptr) {}
FORCEINLINE MinerShare(const difficulty_type& w, const Wallet* x) : m_weight(w), m_wallet(x) {}

uint64_t m_weight;
difficulty_type m_weight;
const Wallet* m_wallet;
};

Expand Down
48 changes: 48 additions & 0 deletions src/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,54 @@ void make_thread_background()
#endif
}

NOINLINE difficulty_type& difficulty_type::operator/=(difficulty_type b)
{
if (*this < b) {
lo = 0;
hi = 0;
return *this;
}

if (*this - b < b) {
lo = 1;
hi = 0;
return *this;
}

if (b.hi == 0) {
return operator/=(b.lo);
}

const uint64_t shift = bsr(b.hi) + 1;
const uint64_t divisor = shiftleft128(b.lo, b.hi, 64 - shift);

uint64_t t;
if (hi < divisor) {
uint64_t r;
t = udiv128(hi, lo, divisor, &r) >> shift;
}
else {
uint64_t r;
t = shiftright128(udiv128(hi - divisor, lo, divisor, &r), 1, shift);
}

difficulty_type product;
product.lo = umul128(b.lo, t, &product.hi);

uint64_t t1, t2;
t1 = umul128(b.hi, t, &t2);
product.hi += t1;

if (t2 || (product.hi < t1) || (*this < product)) {
--t;
}

lo = t;
hi = 0;

return *this;
}

NOINLINE bool difficulty_type::check_pow(const hash& pow_hash) const
{
const uint64_t* a = reinterpret_cast<const uint64_t*>(pow_hash.h);
Expand Down
Loading

0 comments on commit 488ed8e

Please sign in to comment.