//--------------------------------------------------------------------------------- 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; }
//--------------------------------------------------------------------------------- bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t already_generated_coins, size_t &total_size, uint64_t &fee) { // Warning: This function takes already_generated_ // coins as an argument and appears to do nothing // with it. CRITICAL_REGION_LOCAL(m_transactions_lock); total_size = 0; fee = 0; // Maximum block size is 130% of the median block size. This gives a // little extra headroom for the max size transaction. size_t max_total_size = (130 * median_size) / 100 - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE; std::unordered_set<crypto::key_image> k_images; auto sorted_it = m_txs_by_fee.begin(); while (sorted_it != m_txs_by_fee.end()) { auto tx_it = m_transactions.find(sorted_it->second); // Can not exceed maximum block size if (max_total_size < total_size + tx_it->second.blob_size) { sorted_it++; continue; } // If adding this tx will make the block size // greater than CRYPTONOTE_GETBLOCKTEMPLATE_MAX // _BLOCK_SIZE bytes, reject the tx; this will // keep block sizes from becoming too unwieldly // to propagate at 60s block times. if ( (total_size + tx_it->second.blob_size) > CRYPTONOTE_GETBLOCKTEMPLATE_MAX_BLOCK_SIZE ) { sorted_it++; continue; } // If we've exceeded the penalty free size, // stop including more tx if (total_size > median_size) break; // Skip transactions that are not ready to be // included into the blockchain or that are // missing key images if (!is_transaction_ready_to_go(tx_it->second) || have_key_images(k_images, tx_it->second.tx)) { sorted_it++; continue; } bl.tx_hashes.push_back(tx_it->first); total_size += tx_it->second.blob_size; fee += tx_it->second.fee; append_key_images(k_images, tx_it->second.tx); sorted_it++; } return true; }
//--------------------------------------------------------------------------------- bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t already_generated_coins, size_t &total_size, uint64_t &fee) { // Warning: This function takes already_generated_ // coins as an argument and appears to do nothing // with it. CRITICAL_REGION_LOCAL(m_transactions_lock); total_size = 0; fee = 0; size_t max_total_size = 2 * median_size - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE; // Max block size std::unordered_set<crypto::key_image> k_images; // Tx size limit as in wallet2.h // tx_pool.cpp uses size_t for tx sizes, whereas // wallet2.h uses uint64_t; just use size_t here // for now size_t upper_transaction_size_limit = ((CRYPTONOTE_BLOCK_GRANTED_FULL_REWARD_ZONE * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE; // Calculate size limit based on median too; useful // for when we actually fix wallet2.h's maximum // allowable tx size // // Can be removed when wallet2.h calculates max // tx size based on the median too; just use // upper_transaction_size_limit_median in all cases size_t upper_transaction_size_limit_median = ((median_size * 125) / 100) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE; if (upper_transaction_size_limit_median > upper_transaction_size_limit) upper_transaction_size_limit = upper_transaction_size_limit_median; BOOST_FOREACH(transactions_container::value_type& tx, m_transactions) { // Can not exceed maximum block size if (max_total_size < total_size + tx.second.blob_size) continue; // Check to see if the minimum fee is included; // exclude tx missing minimum fee if (tx.second.fee < DEFAULT_FEE) continue; // Skip transactions that are too large // TODO: Correct upper_transactions_size_limit // such that it is based on median block size; // We need to make a similar patch for // wallet2.h if (tx.second.blob_size > upper_transaction_size_limit) continue; // If adding this tx will make the block size // greater than 130% of the median, reject the // tx; this will keep down largely punitive tx // from being included if ( (total_size + tx.second.blob_size) > ((130 * median_size) / 100) ) continue; // If we've exceeded the penalty free size, // stop including more tx if (total_size > median_size) break; // Skip transactions that are not ready to be // included into the blockchain or that are // missing key images if (!is_transaction_ready_to_go(tx.second) || have_key_images(k_images, tx.second.tx)) continue; bl.tx_hashes.push_back(tx.first); total_size += tx.second.blob_size; fee += tx.second.fee; append_key_images(k_images, tx.second.tx); } return true; }