diff options
Diffstat (limited to 'src/cryptonote_core')
-rw-r--r-- | src/cryptonote_core/blockchain.cpp | 60 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_core.cpp | 7 | ||||
-rw-r--r-- | src/cryptonote_core/tx_pool.cpp | 57 | ||||
-rw-r--r-- | src/cryptonote_core/tx_pool.h | 5 |
4 files changed, 109 insertions, 20 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index e3450491b..b7e9f4ca2 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1176,9 +1176,18 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl } } - std::vector<uint64_t> last_blocks_weights; - get_last_n_blocks_weights(last_blocks_weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW); - if (!get_block_reward(epee::misc_utils::median(last_blocks_weights), cumulative_block_weight, already_generated_coins, base_reward, version)) + uint64_t median_weight; + if (version >= HF_VERSION_EFFECTIVE_SHORT_TERM_MEDIAN_IN_PENALTY) + { + median_weight = m_current_block_cumul_weight_median; + } + else + { + std::vector<uint64_t> last_blocks_weights; + get_last_n_blocks_weights(last_blocks_weights, CRYPTONOTE_REWARD_BLOCKS_WINDOW); + median_weight = epee::misc_utils::median(last_blocks_weights); + } + if (!get_block_reward(median_weight, cumulative_block_weight, already_generated_coins, base_reward, version)) { MERROR_VER("block weight " << cumulative_block_weight << " is bigger than allowed for this blockchain"); return false; @@ -1694,7 +1703,8 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id // Check the block's hash against the difficulty target for its alt chain difficulty_type current_diff = get_next_difficulty_for_alternative_chain(alt_chain, bei); CHECK_AND_ASSERT_MES(current_diff, false, "!!!!!!! DIFFICULTY OVERHEAD !!!!!!!"); - crypto::hash proof_of_work = null_hash; + crypto::hash proof_of_work; + memset(proof_of_work.data, 0xff, sizeof(proof_of_work.data)); if (b.major_version >= RX_BLOCK_VERSION) { crypto::hash seedhash = null_hash; @@ -1750,6 +1760,34 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id } bei.cumulative_difficulty += current_diff; + bei.block_cumulative_weight = cryptonote::get_transaction_weight(b.miner_tx); + for (const crypto::hash &txid: b.tx_hashes) + { + cryptonote::tx_memory_pool::tx_details td; + cryptonote::blobdata blob; + if (m_tx_pool.get_transaction_info(txid, td)) + { + bei.block_cumulative_weight += td.weight; + } + else if (m_db->get_pruned_tx_blob(txid, blob)) + { + cryptonote::transaction tx; + if (!cryptonote::parse_and_validate_tx_base_from_blob(blob, tx)) + { + MERROR_VER("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative) refers to unparsable transaction hash " << txid << "."); + bvc.m_verifivation_failed = true; + return false; + } + bei.block_cumulative_weight += cryptonote::get_pruned_transaction_weight(tx); + } + else + { + // we can't determine the block weight, set it to 0 and break out of the loop + bei.block_cumulative_weight = 0; + break; + } + } + // add block to alternate blocks storage, // as well as the current "alt chain" container CHECK_AND_ASSERT_MES(!m_db->get_alt_block(id, NULL, NULL), false, "insertion of new alternative block returned as it already exists"); @@ -3319,8 +3357,8 @@ uint64_t Blockchain::get_dynamic_base_fee(uint64_t block_reward, size_t median_b if (version >= HF_VERSION_PER_BYTE_FEE) { lo = mul128(block_reward, DYNAMIC_FEE_REFERENCE_TRANSACTION_WEIGHT, &hi); - div128_32(hi, lo, min_block_weight, &hi, &lo); - div128_32(hi, lo, median_block_weight, &hi, &lo); + div128_64(hi, lo, min_block_weight, &hi, &lo, NULL, NULL); + div128_64(hi, lo, median_block_weight, &hi, &lo, NULL, NULL); assert(hi == 0); lo /= 5; return lo; @@ -3330,12 +3368,7 @@ uint64_t Blockchain::get_dynamic_base_fee(uint64_t block_reward, size_t median_b uint64_t unscaled_fee_base = (fee_base * min_block_weight / median_block_weight); lo = mul128(unscaled_fee_base, block_reward, &hi); - static_assert(DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD % 1000000 == 0, "DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD must be divisible by 1000000"); - static_assert(DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD / 1000000 <= std::numeric_limits<uint32_t>::max(), "DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD is too large"); - - // divide in two steps, since the divisor must be 32 bits, but DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD isn't - div128_32(hi, lo, DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD / 1000000, &hi, &lo); - div128_32(hi, lo, 1000000, &hi, &lo); + div128_64(hi, lo, DYNAMIC_FEE_PER_KB_BASE_BLOCK_REWARD, &hi, &lo, NULL, NULL); assert(hi == 0); // quantize fee up to 8 decimals @@ -3702,7 +3735,8 @@ leave: TIME_MEASURE_START(longhash_calculating_time); - crypto::hash proof_of_work = null_hash; + crypto::hash proof_of_work; + memset(proof_of_work.data, 0xff, sizeof(proof_of_work.data)); // Formerly the code below contained an if loop with the following condition // !m_checkpoints.is_in_checkpoint_zone(get_current_blockchain_height()) diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index b831cc9ff..5a303a67e 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -1027,11 +1027,7 @@ namespace cryptonote if (already_have[i]) continue; - // if it's a pruned tx from an incoming block, we'll get a weight that's technically - // different from the actual transaction weight, but it's OK for our use. Those txes - // will be ignored when mining, and using that "pruned" weight seems appropriate for - // keeping the txpool size constrained - const uint64_t weight = results[i].tx.pruned ? 0 : get_transaction_weight(results[i].tx, it->blob.size()); + const uint64_t weight = results[i].tx.pruned ? get_pruned_transaction_weight(results[i].tx) : get_transaction_weight(results[i].tx, it->blob.size()); ok &= add_new_tx(results[i].tx, results[i].hash, tx_blobs[i].blob, weight, tvc[i], keeped_by_block, relayed, do_not_relay); if(tvc[i].m_verifivation_failed) {MERROR_VER("Transaction verification failed: " << results[i].hash);} @@ -1367,6 +1363,7 @@ namespace cryptonote { block_complete_entry bce; bce.block = cryptonote::block_to_blob(b); + bce.block_weight = 0; // we can leave it to 0, those txes aren't pruned for (const auto &tx_hash: b.tx_hashes) { cryptonote::blobdata txblob; diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 3a6a3833d..0d70f2992 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -259,7 +259,7 @@ namespace cryptonote m_blockchain.add_txpool_tx(id, blob, meta); if (!insert_key_images(tx, id, kept_by_block)) return false; - m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id); + m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)(tx_weight ? tx_weight : 1), receive_time), id); lock.commit(); } catch (const std::exception &e) @@ -305,7 +305,7 @@ namespace cryptonote m_blockchain.add_txpool_tx(id, blob, meta); if (!insert_key_images(tx, id, kept_by_block)) return false; - m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)tx_weight, receive_time), id); + m_txs_by_fee_and_receive_time.emplace(std::pair<double, std::time_t>(fee / (double)(tx_weight ? tx_weight : 1), receive_time), id); lock.commit(); } catch (const std::exception &e) @@ -518,6 +518,59 @@ namespace cryptonote return true; } //--------------------------------------------------------------------------------- + bool tx_memory_pool::get_transaction_info(const crypto::hash &txid, tx_details &td) const + { + PERF_TIMER(get_transaction_info); + CRITICAL_REGION_LOCAL(m_transactions_lock); + CRITICAL_REGION_LOCAL1(m_blockchain); + + try + { + LockedTXN lock(m_blockchain); + txpool_tx_meta_t meta; + if (!m_blockchain.get_txpool_tx_meta(txid, meta)) + { + MERROR("Failed to find tx in txpool"); + return false; + } + cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(txid); + auto ci = m_parsed_tx_cache.find(txid); + if (ci != m_parsed_tx_cache.end()) + { + td.tx = ci->second; + } + else if (!(meta.pruned ? parse_and_validate_tx_base_from_blob(txblob, td.tx) : parse_and_validate_tx_from_blob(txblob, td.tx))) + { + MERROR("Failed to parse tx from txpool"); + return false; + } + else + { + td.tx.set_hash(txid); + } + td.blob_size = txblob.size(); + td.weight = meta.weight; + td.fee = meta.fee; + td.max_used_block_id = meta.max_used_block_id; + td.max_used_block_height = meta.max_used_block_height; + td.kept_by_block = meta.kept_by_block; + td.last_failed_height = meta.last_failed_height; + td.last_failed_id = meta.last_failed_id; + td.receive_time = meta.receive_time; + td.last_relayed_time = meta.last_relayed_time; + td.relayed = meta.relayed; + td.do_not_relay = meta.do_not_relay; + td.double_spend_seen = meta.double_spend_seen; + } + catch (const std::exception &e) + { + MERROR("Failed to get tx from txpool: " << e.what()); + return false; + } + + return true; + } + //--------------------------------------------------------------------------------- void tx_memory_pool::on_idle() { m_remove_stuck_tx_interval.do_call([this](){return remove_stuck_transactions();}); diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 99182cd0d..dec7e3cd9 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -429,6 +429,11 @@ namespace cryptonote bool double_spend_seen; //!< true iff another tx was seen double spending this one }; + /** + * @brief get infornation about a single transaction + */ + bool get_transaction_info(const crypto::hash &txid, tx_details &td) const; + private: /** |