From e9a2b6fbb7f933fd345a48f9f98eb53a5d9a04e2 Mon Sep 17 00:00:00 2001 From: Some Random Crypto Guy Date: Fri, 27 Dec 2024 15:36:41 +0000 Subject: [PATCH] additional checks needed for protocol_tx validation --- src/cryptonote_core/blockchain.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index cfb48f14f..54c88b4d0 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -1450,6 +1450,13 @@ bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height, bool Blockchain::prevalidate_protocol_transaction(const block& b, uint64_t height, uint8_t hf_version) { LOG_PRINT_L3("Blockchain::" << __func__); + if (height == 0) { + // Genesis block exception + CHECK_AND_ASSERT_MES(b.protocol_tx.version == 1, false, "Invalid genesis protocol transaction version"); + CHECK_AND_ASSERT_MES(b.protocol_tx.vin.size() == 0, false, "genesis protocol transaction in the block has inputs"); + CHECK_AND_ASSERT_MES(b.protocol_tx.vout.size() == 0, false, "genesis protocol transaction in the block has outputs"); + return true; + } CHECK_AND_ASSERT_MES(b.protocol_tx.vin.size() == 1, false, "coinbase protocol transaction in the block has no inputs"); CHECK_AND_ASSERT_MES(b.protocol_tx.vin[0].type() == typeid(txin_gen), false, "coinbase protocol transaction in the block has the wrong type"); CHECK_AND_ASSERT_MES(b.protocol_tx.version > 1, false, "Invalid coinbase protocol transaction version"); @@ -1530,6 +1537,14 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height, { LOG_PRINT_L3("Blockchain::" << __func__); + if (height == 0) { + // Genesis block exception + CHECK_AND_ASSERT_MES(b.protocol_tx.version == 1, false, "Invalid genesis protocol transaction version"); + CHECK_AND_ASSERT_MES(b.protocol_tx.vin.size() == 0, false, "genesis protocol transaction in the block has inputs"); + CHECK_AND_ASSERT_MES(b.protocol_tx.vout.size() == 0, false, "genesis protocol transaction in the block has outputs"); + return true; + } + // if nothing is created by this TX - check no money is included size_t vout_size = b.protocol_tx.vout.size(); CHECK_AND_ASSERT_MES(b.protocol_tx.vin.size() == 1, false, "coinbase protocol transaction in the block has no inputs"); @@ -1557,7 +1572,11 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height, return false; } + // Check we have the correct number of entries + CHECK_AND_ASSERT_MES(b.protocol_tx.vout.size() == yield_payouts.size(), false, "Invalid number of outputs in protocol_tx - aborting"); + // go through each vout and validate + std::set used_keys; for (auto& o : b.protocol_tx.vout) { // gather the output data uint64_t out_amount; @@ -1581,6 +1600,15 @@ bool Blockchain::validate_protocol_transaction(const block& b, uint64_t height, return false; } + // Check if key has already been seen + if (used_keys.count(out_key) != 0) { + LOG_ERROR("Block at height: " << height << " - Duplicated output key " << out_key << " for protocol TX - aborting"); + return false; + } + + // Add key to list of already-seen + used_keys.insert(out_key); + // check if there is entry in the yield payouts for this output auto found = std::find_if(yield_payouts.begin(), yield_payouts.end(), [&](const std::pair& p) { return p.first.return_address == out_key;