From 528664b1c86849e848b5aeedca7c33297e1934de Mon Sep 17 00:00:00 2001 From: jeffro256 Date: Mon, 17 Mar 2025 08:40:04 -0500 Subject: [PATCH] cryptonote_protocol: fix handling of pruned blocks during sync --- src/cryptonote_core/blockchain.cpp | 2 +- .../cryptonote_protocol_handler.inl | 38 +++++++++++++++---- 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 1fd31a995..15dc4160e 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -4260,7 +4260,7 @@ leave: { tx = std::move(extra_txs_it->second.first); txblob = std::move(extra_txs_it->second.second); - tx_weight = get_transaction_weight(tx, txblob.size()); + tx_weight = tx.pruned ? get_pruned_transaction_weight(tx) : get_transaction_weight(tx, txblob.size()); fee = get_tx_fee(tx); pruned = tx.pruned; extra_block_txs.txs_by_txid.erase(extra_txs_it); diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl index 71f4387d0..56527d6dc 100644 --- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl +++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl @@ -81,6 +81,7 @@ namespace cryptonote inline bool make_pool_supplement_from_block_entry( const std::vector& tx_entries, const CryptoHashContainer& blk_tx_hashes, + const bool allow_pruned, cryptonote::pool_supplement& pool_supplement) { pool_supplement.nic_verified_hf_version = 0; @@ -91,7 +92,7 @@ namespace cryptonote return false; } - for (const auto& tx_entry: tx_entries) + for (const cryptonote::tx_blob_entry& tx_entry: tx_entries) { if (tx_entry.blob.size() > get_max_tx_size()) { @@ -99,17 +100,38 @@ namespace cryptonote return false; } + const bool is_pruned = tx_entry.prunable_hash != crypto::null_hash; + if (is_pruned && !allow_pruned) + { + MERROR("Pruned transaction not allowed here"); + return false; + } + cryptonote::transaction tx; crypto::hash tx_hash; - if (!cryptonote::parse_and_validate_tx_from_blob(tx_entry.blob, tx, tx_hash) - || !blk_tx_hashes.count(tx_hash) - || tx.pruned) + bool parse_success = false; + if (is_pruned) { - MERROR("failed to parse and/or validate unpruned transaction as inside block: " + if ((parse_success = cryptonote::parse_and_validate_tx_base_from_blob(tx_entry.blob, tx))) + tx_hash = cryptonote::get_pruned_transaction_hash(tx, tx_entry.prunable_hash); + } + else + { + parse_success = cryptonote::parse_and_validate_tx_from_blob(tx_entry.blob, tx, tx_hash); + } + + if (!parse_success) + { + MERROR("failed to parse and/or validate transaction: " << epee::string_tools::buff_to_hex_nodelimer(tx_entry.blob) ); return false; } + else if (!blk_tx_hashes.count(tx_hash)) + { + MERROR("transaction " << tx_hash << " not in block"); + return false; + } pool_supplement.txs_by_txid.emplace(tx_hash, std::make_pair(std::move(tx), tx_entry.blob)); } @@ -146,7 +168,9 @@ namespace cryptonote return false; } - return make_pool_supplement_from_block_entry(blk_entry.txs, blk_tx_hashes, pool_supplement); + // We set `allow_pruned` equal to whether this block entry is pruned since the pruned flag + // should be checked anyways by the time we deserialize transactions + return make_pool_supplement_from_block_entry(blk_entry.txs, blk_tx_hashes, blk_entry.pruned, pool_supplement); } @@ -624,7 +648,7 @@ namespace cryptonote // can skip the mempool for faster block propagation. Later in the function, we will erase all // transactions from the relayed block. pool_supplement extra_block_txs; - if (!make_pool_supplement_from_block_entry(arg.b.txs, blk_txids_set, extra_block_txs)) + if (!make_pool_supplement_from_block_entry(arg.b.txs, blk_txids_set, /*allow_pruned=*/false, extra_block_txs)) { LOG_ERROR_CCONTEXT (