From f274087a484c0413738fc6e889d60d873e8c5a04 Mon Sep 17 00:00:00 2001 From: who-biz <37732338+who-biz@users.noreply.github.com> Date: Sun, 24 Nov 2019 04:57:23 -0500 Subject: [PATCH] Rework branching in mining algo, add modulo helpers --- src/common/int-util.h | 117 ++++++++++++++++++ .../cryptonote_format_utils.cpp | 30 +++-- 2 files changed, 136 insertions(+), 11 deletions(-) diff --git a/src/common/int-util.h b/src/common/int-util.h index 726922ab..fa0931a2 100644 --- a/src/common/int-util.h +++ b/src/common/int-util.h @@ -85,6 +85,123 @@ static inline uint64_t add(uint64_t a, uint64_t b) { else return add(a ^ b, (a & b) << 1); } +static inline uint32_t mod3( uint32_t a ){ + a = add(((a >> 2) & 0x33333333),(a & 0x33333333)); + a = add(((a >> 4) & 0x07070707),(a & 0x07070707)); + a = add(((a >> 8) & 0x000F000F),(a & 0x000F000F)); + a = add(((a >> 16) ),(a & 0x0000001F)); + a = add(((a >> 2) & 0x33333333),(a & 0x33333333)); + a = add(((a >> 4) ),(a & 0x07070707)); + a = add(((a >> 2) ),(a & 0x33333333)); + if (a > 2) a = a - 3; + return a; +} + +/*static inline uint32_t modular_pow3(uint32_t base, uint32_t exponent, uint32_t result) +{ + result = 1; + base = mod3(base); + while (exponent > 0) { + if (exponent & 1) + result = mod3(result * base); + exponent = exponent >> 1; + base = mod3(base * base); + } + return result; +}*/ + +static inline uint32_t mod_mersenne(uint32_t const num, uint32_t const s) // s = (mersenne + 1), i.e. pow2 +{ + // https://graphics.stanford.edu/~seander/bithacks.html#ModulusDivisionParallel + const unsigned int M[] = + { + 0x00000000, 0x55555555, 0x33333333, 0xc71c71c7, + 0x0f0f0f0f, 0xc1f07c1f, 0x3f03f03f, 0xf01fc07f, + 0x00ff00ff, 0x07fc01ff, 0x3ff003ff, 0xffc007ff, + 0xff000fff, 0xfc001fff, 0xf0003fff, 0xc0007fff, + 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, + 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, + 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, + 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff + }; + + const unsigned int Q[][6] = + { + { 0, 0, 0, 0, 0, 0}, {16, 8, 4, 2, 1, 1}, {16, 8, 4, 2, 2, 2}, + {15, 6, 3, 3, 3, 3}, {16, 8, 4, 4, 4, 4}, {15, 5, 5, 5, 5, 5}, + {12, 6, 6, 6 , 6, 6}, {14, 7, 7, 7, 7, 7}, {16, 8, 8, 8, 8, 8}, + { 9, 9, 9, 9, 9, 9}, {10, 10, 10, 10, 10, 10}, {11, 11, 11, 11, 11, 11}, + {12, 12, 12, 12, 12, 12}, {13, 13, 13, 13, 13, 13}, {14, 14, 14, 14, 14, 14}, + {15, 15, 15, 15, 15, 15}, {16, 16, 16, 16, 16, 16}, {17, 17, 17, 17, 17, 17}, + {18, 18, 18, 18, 18, 18}, {19, 19, 19, 19, 19, 19}, {20, 20, 20, 20, 20, 20}, + {21, 21, 21, 21, 21, 21}, {22, 22, 22, 22, 22, 22}, {23, 23, 23, 23, 23, 23}, + {24, 24, 24, 24, 24, 24}, {25, 25, 25, 25, 25, 25}, {26, 26, 26, 26, 26, 26}, + {27, 27, 27, 27, 27, 27}, {28, 28, 28, 28, 28, 28}, {29, 29, 29, 29, 29, 29}, + {30, 30, 30, 30, 30, 30}, {31, 31, 31, 31, 31, 31} + }; + + const unsigned int R[][6] = + { + {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, + {0x0000ffff, 0x000000ff, 0x0000000f, 0x00000003, 0x00000001, 0x00000001}, + {0x0000ffff, 0x000000ff, 0x0000000f, 0x00000003, 0x00000003, 0x00000003}, + {0x00007fff, 0x0000003f, 0x00000007, 0x00000007, 0x00000007, 0x00000007}, + {0x0000ffff, 0x000000ff, 0x0000000f, 0x0000000f, 0x0000000f, 0x0000000f}, + {0x00007fff, 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f, 0x0000001f}, + {0x00000fff, 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f, 0x0000003f}, + {0x00003fff, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f, 0x0000007f}, + {0x0000ffff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff}, + {0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff, 0x000001ff}, + {0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff, 0x000003ff}, + {0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff, 0x000007ff}, + {0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff, 0x00000fff}, + {0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff, 0x00001fff}, + {0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff, 0x00003fff}, + {0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff, 0x00007fff}, + {0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff, 0x0000ffff}, + {0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff, 0x0001ffff}, + {0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff, 0x0003ffff}, + {0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff, 0x0007ffff}, + {0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff, 0x000fffff}, + {0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff, 0x001fffff}, + {0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff, 0x003fffff}, + {0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff, 0x007fffff}, + {0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff, 0x00ffffff}, + {0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff, 0x01ffffff}, + {0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff, 0x03ffffff}, + {0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff, 0x07ffffff}, + {0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff, 0x0fffffff}, + {0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff, 0x1fffffff}, + {0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff, 0x3fffffff}, + {0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff} + }; + + const unsigned int d = (1 << s) - 1; + unsigned int m; + + m = (num & M[s]) + ((num >> s) & M[s]); + + for (const unsigned int * q = &Q[s][0], * r = &R[s][0]; m > d; q++, r++) + { + m = (m >> *q) + (m & *r); + } + + m = m == d ? 0 : m; + return m; +} + +static inline uint32_t div3(uint32_t num) +{ + uint32_t sum = 0; + while (num > 3) { + sum = add(num >> 2, sum); + num = add(num >> 2, num & 3); + } + if (num == 3) + sum = add(sum, 1); + return sum; +} + static inline uint64_t mul128(uint64_t multiplier, uint64_t multiplicand, uint64_t* product_hi) { // multiplier = ab = a * 2^32 + b // multiplicand = cd = c * 2^32 + d diff --git a/src/cryptonote_basic/cryptonote_format_utils.cpp b/src/cryptonote_basic/cryptonote_format_utils.cpp index 1cf339d3..c0eaa5b6 100644 --- a/src/cryptonote_basic/cryptonote_format_utils.cpp +++ b/src/cryptonote_basic/cryptonote_format_utils.cpp @@ -949,20 +949,28 @@ namespace cryptonote uint32_t id_num = std::strtoul(subhash.c_str(), NULL, 16); LOG_PRINT_L2("\nPRNG from previous block ID : " << id_num); + // guard against small probability of zero case + id_num = id_num < 1 ? 1 : id_num; // in previous hash's first 6 characters - if (id_num < 1) { // guard against small probability of zero case - id_num = 1; } // in previous hash's first 6 characters - - const uint64_t m_stamp = b.timestamp; - bool two = false; - two = id_num && !(id_num & (id_num - 1)); - if (two) { + uint64_t m_stamp = b.timestamp; + bool two = id_num && !(id_num & (id_num - 1)); + if (!two) { + uint32_t m = add(id_num, 1); + bool mersenne = m && !(m & (m - 1)); + if (!mersenne) { + if (!mod3(m_stamp) && !mod3(id_num)) { + // MWARNING("Encountered reducible operands, dividing by 3!"); + uint32_t inner = div3(m_stamp) % div3(id_num); + its = add(cn_iters, (add(inner, height) & 0x7FFF)); + } + its = add(cn_iters, (add(m_stamp % id_num, height) & 0x7FFF)); + } else { + its = add(cn_iters,(add(mod_mersenne(m_stamp,m), height) & 0x7FFF)); + } + } else { its = add(cn_iters, (add(m_stamp & (id_num - 1), height) & 0x7FFF)); - } - else if (!two) { - its = add(cn_iters, (add(m_stamp % id_num, height) & 0x7FFF)); } - LOG_PRINT_L2("\nIterations : "<< its); + LOG_PRINT_L2("\nIterations : "<< its); } crypto::cn_slow_hash(bd.data(), bd.size(), res, cn_variant, its); return true;