aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_core')
-rw-r--r--src/cryptonote_core/blockchain.cpp65
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp1
-rw-r--r--src/cryptonote_core/tx_pool.cpp59
-rw-r--r--src/cryptonote_core/tx_pool.h7
4 files changed, 114 insertions, 18 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index b672ccd6e..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;
@@ -1723,6 +1733,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
{
MERROR_VER("Block with id: " << id << std::endl << " for alternative chain, does not have enough proof of work: " << proof_of_work << std::endl << " expected difficulty: " << current_diff);
bvc.m_verifivation_failed = true;
+ bvc.m_bad_pow = true;
return false;
}
@@ -1749,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");
@@ -3318,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;
@@ -3329,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
@@ -3431,7 +3465,8 @@ uint64_t Blockchain::get_dynamic_base_fee_estimate(uint64_t grace_blocks) const
}
const bool use_long_term_median_in_fee = version >= HF_VERSION_LONG_TERM_BLOCK_WEIGHT;
- uint64_t fee = get_dynamic_base_fee(base_reward, use_long_term_median_in_fee ? m_long_term_effective_median_block_weight : median, version);
+ const uint64_t use_median_value = use_long_term_median_in_fee ? std::min<uint64_t>(median, m_long_term_effective_median_block_weight) : median;
+ const uint64_t fee = get_dynamic_base_fee(base_reward, use_median_value, version);
const bool per_byte = version < HF_VERSION_PER_BYTE_FEE;
MDEBUG("Estimating " << grace_blocks << "-block fee at " << print_money(fee) << "/" << (per_byte ? "byte" : "kB"));
return fee;
@@ -3700,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())
@@ -3749,6 +3785,7 @@ leave:
{
MERROR_VER("Block with id: " << id << std::endl << "does not have enough proof of work: " << proof_of_work << " at height " << blockchain_height << ", unexpected difficulty: " << current_diffic);
bvc.m_verifivation_failed = true;
+ bvc.m_bad_pow = true;
goto leave;
}
}
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index b831cc9ff..eed5317e1 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -1367,6 +1367,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 0b7e5c199..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();});
@@ -911,7 +964,7 @@ namespace cryptonote
return true;
}
//---------------------------------------------------------------------------------
- bool tx_memory_pool::check_for_key_images(const std::vector<crypto::key_image>& key_images, std::vector<bool> spent) const
+ bool tx_memory_pool::check_for_key_images(const std::vector<crypto::key_image>& key_images, std::vector<bool>& spent) const
{
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h
index 895014d17..dec7e3cd9 100644
--- a/src/cryptonote_core/tx_pool.h
+++ b/src/cryptonote_core/tx_pool.h
@@ -301,7 +301,7 @@ namespace cryptonote
*
* @return true
*/
- bool check_for_key_images(const std::vector<crypto::key_image>& key_images, std::vector<bool> spent) const;
+ bool check_for_key_images(const std::vector<crypto::key_image>& key_images, std::vector<bool>& spent) const;
/**
* @brief get a specific transaction from the pool
@@ -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:
/**