blockchain: forbid v1 coinbase from v12

This commit is contained in:
moneromooo-monero 2019-05-24 22:41:39 +00:00
parent 459beb50d4
commit 26072f1393
No known key found for this signature in database
GPG Key ID: 686F07454D6CEFC3
6 changed files with 38 additions and 5 deletions

View File

@ -150,6 +150,7 @@
#define HF_VERSION_SMALLER_BP 10 #define HF_VERSION_SMALLER_BP 10
#define HF_VERSION_LONG_TERM_BLOCK_WEIGHT 10 #define HF_VERSION_LONG_TERM_BLOCK_WEIGHT 10
#define HF_VERSION_MIN_2_OUTPUTS 12 #define HF_VERSION_MIN_2_OUTPUTS 12
#define HF_VERSION_MIN_V2_COINBASE_TX 12
#define PER_KB_FEE_QUANTIZATION_DECIMALS 8 #define PER_KB_FEE_QUANTIZATION_DECIMALS 8

View File

@ -1202,11 +1202,12 @@ difficulty_type Blockchain::get_next_difficulty_for_alternative_chain(const std:
// one input, of type txin_gen, with height set to the block's height // one input, of type txin_gen, with height set to the block's height
// correct miner tx unlock time // correct miner tx unlock time
// a non-overflowing tx amount (dubious necessity on this check) // a non-overflowing tx amount (dubious necessity on this check)
bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height) bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height, uint8_t hf_version)
{ {
LOG_PRINT_L3("Blockchain::" << __func__); LOG_PRINT_L3("Blockchain::" << __func__);
CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, false, "coinbase transaction in the block has no inputs"); CHECK_AND_ASSERT_MES(b.miner_tx.vin.size() == 1, false, "coinbase transaction in the block has no inputs");
CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(txin_gen), false, "coinbase transaction in the block has the wrong type"); CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(txin_gen), false, "coinbase transaction in the block has the wrong type");
CHECK_AND_ASSERT_MES(b.miner_tx.version > 1 || hf_version < HF_VERSION_MIN_V2_COINBASE_TX, false, "Invalid coinbase transaction version");
if(boost::get<txin_gen>(b.miner_tx.vin[0]).height != height) if(boost::get<txin_gen>(b.miner_tx.vin[0]).height != height)
{ {
MWARNING("The miner transaction in block has invalid height: " << boost::get<txin_gen>(b.miner_tx.vin[0]).height << ", expected: " << height); MWARNING("The miner transaction in block has invalid height: " << boost::get<txin_gen>(b.miner_tx.vin[0]).height << ", expected: " << height);
@ -1713,6 +1714,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
} }
// this is a cheap test // this is a cheap test
const uint8_t hf_version = m_hardfork->get_ideal_version(block_height);
if (!m_hardfork->check_for_height(b, block_height)) if (!m_hardfork->check_for_height(b, block_height))
{ {
LOG_PRINT_L1("Block with id: " << id << std::endl << "has old version for height " << block_height); LOG_PRINT_L1("Block with id: " << id << std::endl << "has old version for height " << block_height);
@ -1770,7 +1772,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
return false; return false;
} }
if(!prevalidate_miner_transaction(b, bei.height)) if(!prevalidate_miner_transaction(b, bei.height, hf_version))
{ {
MERROR_VER("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative) has incorrect miner transaction."); MERROR_VER("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative) has incorrect miner transaction.");
bvc.m_verifivation_failed = true; bvc.m_verifivation_failed = true;
@ -3615,9 +3617,10 @@ leave:
} }
// this is a cheap test // this is a cheap test
const uint8_t hf_version = get_current_hard_fork_version();
if (!m_hardfork->check(bl)) if (!m_hardfork->check(bl))
{ {
MERROR_VER("Block with id: " << id << std::endl << "has old version: " << (unsigned)bl.major_version << std::endl << "current: " << (unsigned)m_hardfork->get_current_version()); MERROR_VER("Block with id: " << id << std::endl << "has old version: " << (unsigned)bl.major_version << std::endl << "current: " << (unsigned)hf_version);
bvc.m_verifivation_failed = true; bvc.m_verifivation_failed = true;
goto leave; goto leave;
} }
@ -3722,7 +3725,7 @@ leave:
TIME_MEASURE_START(t3); TIME_MEASURE_START(t3);
// sanity check basic miner tx properties; // sanity check basic miner tx properties;
if(!prevalidate_miner_transaction(bl, blockchain_height)) if(!prevalidate_miner_transaction(bl, blockchain_height, hf_version))
{ {
MERROR_VER("Block with id: " << id << " failed to pass prevalidation"); MERROR_VER("Block with id: " << id << " failed to pass prevalidation");
bvc.m_verifivation_failed = true; bvc.m_verifivation_failed = true;

View File

@ -1246,10 +1246,11 @@ namespace cryptonote
* *
* @param b the block containing the miner transaction * @param b the block containing the miner transaction
* @param height the height at which the block will be added * @param height the height at which the block will be added
* @param hf_version the consensus rules to apply
* *
* @return false if anything is found wrong with the miner transaction, otherwise true * @return false if anything is found wrong with the miner transaction, otherwise true
*/ */
bool prevalidate_miner_transaction(const block& b, uint64_t height); bool prevalidate_miner_transaction(const block& b, uint64_t height, uint8_t hf_version);
/** /**
* @brief validates a miner (coinbase) transaction * @brief validates a miner (coinbase) transaction

View File

@ -640,3 +640,18 @@ bool gen_block_invalid_binary_format::check_all_blocks_purged(cryptonote::core&
return true; return true;
} }
bool gen_block_late_v1_coinbase_tx::generate(std::vector<test_event_entry>& events) const
{
BLOCK_VALIDATION_INIT_GENERATE();
block blk_1;
generator.construct_block_manually(blk_1, blk_0, miner_account,
test_generator::bf_major_ver | test_generator::bf_minor_ver,
HF_VERSION_MIN_V2_COINBASE_TX, HF_VERSION_MIN_V2_COINBASE_TX);
events.push_back(blk_1);
DO_CALLBACK(events, "check_block_purged");
return true;
}

View File

@ -206,3 +206,15 @@ struct gen_block_invalid_binary_format : public test_chain_unit_base
private: private:
size_t m_corrupt_blocks_begin_idx; size_t m_corrupt_blocks_begin_idx;
}; };
struct gen_block_late_v1_coinbase_tx : public gen_block_verification_base<1>
{
bool generate(std::vector<test_event_entry>& events) const;
};
template<>
struct get_test_options<gen_block_late_v1_coinbase_tx> {
const std::pair<uint8_t, uint64_t> hard_forks[3] = {std::make_pair(1, 0), std::make_pair(HF_VERSION_MIN_V2_COINBASE_TX, 1), std::make_pair(0, 0)};
const cryptonote::test_options test_options = {
hard_forks, 0
};
};

View File

@ -133,6 +133,7 @@ int main(int argc, char* argv[])
GENERATE_AND_PLAY(gen_block_has_invalid_tx); GENERATE_AND_PLAY(gen_block_has_invalid_tx);
GENERATE_AND_PLAY(gen_block_is_too_big); GENERATE_AND_PLAY(gen_block_is_too_big);
GENERATE_AND_PLAY(gen_block_invalid_binary_format); // Takes up to 3 hours, if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 500, up to 30 minutes, if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 10 GENERATE_AND_PLAY(gen_block_invalid_binary_format); // Takes up to 3 hours, if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 500, up to 30 minutes, if CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW == 10
GENERATE_AND_PLAY(gen_block_late_v1_coinbase_tx);
// Transaction verification tests // Transaction verification tests
GENERATE_AND_PLAY(gen_tx_big_version); GENERATE_AND_PLAY(gen_tx_big_version);