//----------------------------------------------------------------------------------------------- uint64_t getPenalizedAmount(uint64_t amount, size_t medianSize, size_t currentBlockSize) { static_assert(sizeof(size_t) >= sizeof(uint32_t), "size_t is too small"); assert(currentBlockSize <= 2 * medianSize); assert(medianSize <= std::numeric_limits<uint32_t>::max()); assert(currentBlockSize <= std::numeric_limits<uint32_t>::max()); if (amount == 0) { return 0; } if (currentBlockSize <= medianSize) { return amount; } uint64_t productHi; uint64_t productLo = mul128(amount, currentBlockSize * (UINT64_C(2) * medianSize - currentBlockSize), &productHi); uint64_t penalizedAmountHi; uint64_t penalizedAmountLo; div128_32(productHi, productLo, static_cast<uint32_t>(medianSize), &penalizedAmountHi, &penalizedAmountLo); div128_32(penalizedAmountHi, penalizedAmountLo, static_cast<uint32_t>(medianSize), &penalizedAmountHi, &penalizedAmountLo); assert(0 == penalizedAmountHi); assert(penalizedAmountLo < amount); return penalizedAmountLo; }
//----------------------------------------------------------------------------------------------- uint64_t getPenalizedAmount(uint64_t amount, size_t medianSize, size_t currentBlockSize) { static_assert(sizeof(size_t) >= sizeof(uint32_t), "size_t is too small"); assert(currentBlockSize <= 2 * medianSize); assert(medianSize <= std::numeric_limits<uint32_t>::max()); assert(currentBlockSize <= std::numeric_limits<uint32_t>::max()); if (amount == 0) { return 0; } if (currentBlockSize <= medianSize) { return amount; } uint64_t productHi; //uint64_t productLo = mul128(amount, currentBlockSize * (UINT64_C(2) * medianSize - currentBlockSize), &productHi); //BUGFIX by Monero Project: 32-bit saturation bug (e.g. ARM7), the result was being treated as 32-bit by default uint64_t multiplicand = UINT64_C(2) * medianSize - currentBlockSize; multiplicand *= currentBlockSize; uint64_t productLo = mul128(amount, multiplicand, &productHi); uint64_t penalizedAmountHi; uint64_t penalizedAmountLo; div128_32(productHi, productLo, static_cast<uint32_t>(medianSize), &penalizedAmountHi, &penalizedAmountLo); div128_32(penalizedAmountHi, penalizedAmountLo, static_cast<uint32_t>(medianSize), &penalizedAmountHi, &penalizedAmountLo); assert(0 == penalizedAmountHi); assert(penalizedAmountLo < amount); return penalizedAmountLo; }
uint64_t Currency::calculateInterest(uint64_t amount, uint32_t term, uint32_t height) const { assert(m_depositMinTerm <= term && term <= m_depositMaxTerm); assert(static_cast<uint64_t>(term)* m_depositMaxTotalRate > m_depositMinTotalRateFactor); uint64_t a = static_cast<uint64_t>(term) * m_depositMaxTotalRate - m_depositMinTotalRateFactor; uint64_t bHi; uint64_t bLo = mul128(amount, a, &bHi); uint64_t cHi; uint64_t cLo; assert(std::numeric_limits<uint32_t>::max() / 100 > m_depositMaxTerm); div128_32(bHi, bLo, static_cast<uint32_t>(100 * m_depositMaxTerm), &cHi, &cLo); assert(cHi == 0); //early depositor multiplier uint64_t interestHi; uint64_t interestLo; if (height <= CryptoNote::parameters::END_MULTIPLIER_BLOCK){ interestLo = mul128(cLo, CryptoNote::parameters::MULTIPLIER_FACTOR, &interestHi); assert(interestHi == 0); } else { interestHi = cHi; interestLo = cLo; } return interestLo; }