Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
bool CodeInterval::update(const Interval& symbol) throw(not_normalized, invalid_symbol)
{
	if(!is_normalized()) {
		throw not_normalized("Interval must be normalized before update.");
	}
	if(symbol.range < 3 || symbol.base + symbol.range < symbol.base) {
		throw invalid_symbol("Invalid symbol interval.");
	}
	
	// Calculate the new base
	uint64 h, l;
	std::tie(h, l) = mul128(symbol.base, range);
	std::tie(h, l) = add128(h, l, symbol.base);
	const uint64 t = h + (l > 0 ? 1 : 0);
	base += t;
	
	// Calculate the new range
	std::tie(h, l) = mul128(symbol.base + symbol.range, range);
	std::tie(h, l) = add128(h, l, symbol.base + symbol.range);
	std::tie(h, l) = add128(h, l, range);
	std::tie(h, l) = add128(h, l, 1);
	range = h - t - 1;
	
	// Return carry
	return base < t;
}
Ejemplo n.º 3
0
//---------------------------------------------------------------------------------
bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t already_generated_coins, uint64_t already_donated_coins, size_t &total_size, uint64_t &fee) {
    typedef transactions_container::value_type txv;
    CRITICAL_REGION_LOCAL(m_transactions_lock);

    std::vector<txv *> txs(m_transactions.size());
    std::transform(m_transactions.begin(), m_transactions.end(), txs.begin(), [](txv &a) -> txv * { return &a; });
    std::sort(txs.begin(), txs.end(), [](txv *a, txv *b) -> bool {
        uint64_t a_hi, a_lo = mul128(a->second.fee, b->second.blob_size, &a_hi);
        uint64_t b_hi, b_lo = mul128(b->second.fee, a->second.blob_size, &b_hi);
        return a_hi > b_hi || (a_hi == b_hi && a_lo > b_lo);
    });

    size_t current_size = 0;
    uint64_t current_fee = 0;
    uint64_t best_money;
    uint64_t max_donation = 0;
    if (!get_block_reward(median_size, CURRENCY_COINBASE_BLOB_RESERVED_SIZE, already_generated_coins, already_donated_coins, best_money, max_donation)) {
        LOG_ERROR("Block with just a miner transaction is already too large!");
        return false;
    }
    size_t best_position = 0;
    total_size = 0;
    fee = 0;

    std::unordered_set<crypto::key_image> k_images;

    for (size_t i = 0; i < txs.size(); i++) {
        txv &tx(*txs[i]);

        if(!is_transaction_ready_to_go(tx.second) || have_key_images(k_images, tx.second.tx)) {
            txs[i] = NULL;
            continue;
        }
        append_key_images(k_images, tx.second.tx);

        current_size += tx.second.blob_size;
        current_fee += tx.second.fee;

        uint64_t current_reward;
        if (!get_block_reward(median_size, current_size + CURRENCY_COINBASE_BLOB_RESERVED_SIZE, already_generated_coins, already_donated_coins, current_reward, max_donation)) {
            break;
        }

        if (best_money < current_reward + current_fee) {
            best_money = current_reward + current_fee;
            best_position = i + 1;
            total_size = current_size;
            fee = current_fee;
        }
    }

    for (size_t i = 0; i < best_position; i++) {
        if (txs[i]) {
            bl.tx_hashes.push_back(txs[i]->first);
        }
    }

    return true;
}
Ejemplo n.º 4
0
  //-----------------------------------------------------------------------------------------------
  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;
  }
Ejemplo n.º 5
0
bool decode_block(const char* block, size_t size, char* res)
{
	assert(1 <= size && size <= full_encoded_block_size);

	int res_size = decoded_block_sizes[size];
	if (res_size <= 0)
		return false; // Invalid block size

	uint64_t res_num = 0;
	uint64_t order = 1;
	for (size_t i = size - 1; i < size; --i)
	{
		int digit = reverse_alphabet(block[i]);
		if (digit < 0)
			return false; // Invalid symbol

		uint64_t product_hi;
		uint64_t tmp = res_num + mul128(order, (uint64_t) digit, &product_hi);
		if (tmp < res_num || 0 != product_hi)
			return false; // Overflow

		res_num = tmp;
		order *= alphabet_size; // Never overflows, 58^10 < 2^64
	}

	if ((size_t)res_size < full_block_size && (UINT64_C(1) << (8 * res_size)) <= res_num)
		return false; // Overflow

	uint_64_to_8be(res_num, res_size, (uint8_t*)(res));

	return true;
}
Ejemplo n.º 6
0
  //-----------------------------------------------------------------------------------------------
  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;
  }
Ejemplo n.º 7
0
static inline void mul_sum_xor_dst(const uint8_t* a, uint8_t* c, uint8_t* dst) {
	uint64_t hi, lo = mul128(((uint64_t*) a)[0], ((uint64_t*) dst)[0], &hi) + ((uint64_t*) c)[1];
	hi += ((uint64_t*) c)[0];

	((uint64_t*) c)[0] = ((uint64_t*) dst)[0] ^ hi;
	((uint64_t*) c)[1] = ((uint64_t*) dst)[1] ^ lo;
	((uint64_t*) dst)[0] = hi;
	((uint64_t*) dst)[1] = lo;
}
Ejemplo n.º 8
0
static void mul(const uint8_t* a, const uint8_t* b, uint8_t* res) {
    uint64_t a0, b0;
    uint64_t hi, lo;

    a0 = SWAP64LE(((uint64_t*) a)[0]);
    b0 = SWAP64LE(((uint64_t*) b)[0]);
    lo = mul128(a0, b0, &hi);
    ((uint64_t*) res)[0] = SWAP64LE(hi);
    ((uint64_t*) res)[1] = SWAP64LE(lo);
}
Ejemplo n.º 9
0
difficulty_type Currency::nextDifficulty(std::vector<uint64_t> timestamps,
  std::vector<difficulty_type> cumulativeDifficulties) const {
  assert(m_difficultyWindow >= 2);

  if (timestamps.size() > m_difficultyWindow) {
    timestamps.resize(m_difficultyWindow);
    cumulativeDifficulties.resize(m_difficultyWindow);
  }

  size_t length = timestamps.size();
  assert(length == cumulativeDifficulties.size());
  assert(length <= m_difficultyWindow);
  if (length <= 1) {
    return 1;
  }

  sort(timestamps.begin(), timestamps.end());

  size_t cutBegin, cutEnd;
  assert(2 * m_difficultyCut <= m_difficultyWindow - 2);
  if (length <= m_difficultyWindow - 2 * m_difficultyCut) {
    cutBegin = 0;
    cutEnd = length;
  } else {
    cutBegin = (length - (m_difficultyWindow - 2 * m_difficultyCut) + 1) / 2;
    cutEnd = cutBegin + (m_difficultyWindow - 2 * m_difficultyCut);
  }
  assert(/*cut_begin >= 0 &&*/ cutBegin + 2 <= cutEnd && cutEnd <= length);
  uint64_t timeSpan = timestamps[cutEnd - 1] - timestamps[cutBegin];
  if (timeSpan == 0) {
    timeSpan = 1;
  }

  difficulty_type totalWork = cumulativeDifficulties[cutEnd - 1] - cumulativeDifficulties[cutBegin];
  assert(totalWork > 0);

  uint64_t low, high;
  low = mul128(totalWork, m_difficultyTarget, &high);
  if (high != 0 || low + timeSpan - 1 < low) {
    return 0;
  }

  return (low + timeSpan - 1) / timeSpan;
}
Ejemplo n.º 10
0
void cryptonight_hash(const char* input, char* output, uint32_t len, int variant, uint64_t height) {
    struct cryptonight_ctx *ctx = alloca(sizeof(struct cryptonight_ctx));
    hash_process(&ctx->state.hs, (const uint8_t*) input, len);
    memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
    memcpy(ctx->aes_key, ctx->state.hs.b, AES_KEY_SIZE);
    ctx->aes_ctx = (oaes_ctx*) oaes_alloc();
    size_t i, j;

    VARIANT1_INIT();
    VARIANT2_INIT(ctx->b, ctx->state);
    VARIANT4_RANDOM_MATH_INIT(ctx->state);

    oaes_key_import_data(ctx->aes_ctx, ctx->aes_key, AES_KEY_SIZE);
    for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) {
        for (j = 0; j < INIT_SIZE_BLK; j++) {
            aesb_pseudo_round(&ctx->text[AES_BLOCK_SIZE * j],
                    &ctx->text[AES_BLOCK_SIZE * j],
                    ctx->aes_ctx->key->exp_data);
        }
        memcpy(&ctx->long_state[i * INIT_SIZE_BYTE], ctx->text, INIT_SIZE_BYTE);
    }

    for (i = 0; i < 16; i++) {
        ctx->a[i] = ctx->state.k[i] ^ ctx->state.k[32 + i];
        ctx->b[i] = ctx->state.k[16 + i] ^ ctx->state.k[48 + i];
    }

    for (i = 0; i < ITER / 2; i++) {
        /* Dependency chain: address -> read value ------+
         * written value <-+ hard function (AES or MUL) <+
         * next address  <-+
         */
        /* Iteration 1 */
        j = e2i(ctx->a);
        aesb_single_round(&ctx->long_state[j * AES_BLOCK_SIZE], ctx->c, ctx->a);
        VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a, ctx->b, ctx->c);
        xor_blocks_dst(ctx->c, ctx->b, &ctx->long_state[j * AES_BLOCK_SIZE]);
        VARIANT1_1((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]);
        /* Iteration 2 */
        j = e2i(ctx->c);

        uint64_t* dst = (uint64_t*)&ctx->long_state[j * AES_BLOCK_SIZE];

        uint64_t t[2];
        t[0] = dst[0];
        t[1] = dst[1];

        VARIANT2_INTEGER_MATH(t, ctx->c);
        copy_block(ctx->a1, ctx->a);
        VARIANT4_RANDOM_MATH(ctx->a, t, r, ctx->b, ctx->b + AES_BLOCK_SIZE);

        uint64_t hi;
        uint64_t lo = mul128(((uint64_t*)ctx->c)[0], t[0], &hi);

        VARIANT2_2();
        VARIANT2_SHUFFLE_ADD(ctx->long_state, j * AES_BLOCK_SIZE, ctx->a1, ctx->b, ctx->c);

        ((uint64_t*)ctx->a)[0] += hi;
        ((uint64_t*)ctx->a)[1] += lo;

        dst[0] = ((uint64_t*)ctx->a)[0];
        dst[1] = ((uint64_t*)ctx->a)[1];

        ((uint64_t*)ctx->a)[0] ^= t[0];
        ((uint64_t*)ctx->a)[1] ^= t[1];

        VARIANT1_2((uint8_t*)&ctx->long_state[j * AES_BLOCK_SIZE]);
        copy_block(ctx->b + AES_BLOCK_SIZE, ctx->b);
        copy_block(ctx->b, ctx->c);
    }

    memcpy(ctx->text, ctx->state.init, INIT_SIZE_BYTE);
    oaes_key_import_data(ctx->aes_ctx, &ctx->state.hs.b[32], AES_KEY_SIZE);
    for (i = 0; i < MEMORY / INIT_SIZE_BYTE; i++) {
        for (j = 0; j < INIT_SIZE_BLK; j++) {
            xor_blocks(&ctx->text[j * AES_BLOCK_SIZE],
                    &ctx->long_state[i * INIT_SIZE_BYTE + j * AES_BLOCK_SIZE]);
            aesb_pseudo_round(&ctx->text[j * AES_BLOCK_SIZE],
                    &ctx->text[j * AES_BLOCK_SIZE],
                    ctx->aes_ctx->key->exp_data);
        }
    }
    memcpy(ctx->state.init, ctx->text, INIT_SIZE_BYTE);
    hash_permutation(&ctx->state.hs);
    /*memcpy(hash, &state, 32);*/
    extra_hashes[ctx->state.hs.b[0] & 3](&ctx->state, 200, output);
    oaes_free((OAES_CTX **) &ctx->aes_ctx);
}