|
|
|
@ -56,6 +56,9 @@
|
|
|
|
|
#include "blocks/blocks.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#undef MONERO_DEFAULT_LOG_CATEGORY
|
|
|
|
|
#define MONERO_DEFAULT_LOG_CATEGORY "blockchain"
|
|
|
|
|
|
|
|
|
|
//#include "serialization/json_archive.h"
|
|
|
|
|
|
|
|
|
|
/* TODO:
|
|
|
|
@ -71,6 +74,8 @@ extern "C" void slow_hash_free_state();
|
|
|
|
|
|
|
|
|
|
DISABLE_VS_WARNINGS(4267)
|
|
|
|
|
|
|
|
|
|
#define MERROR_VER(x) MCERROR("verify", x)
|
|
|
|
|
|
|
|
|
|
// used to overestimate the block reward when estimating a per kB to use
|
|
|
|
|
#define BLOCK_REWARD_OVERESTIMATE (10 * 1000000000000)
|
|
|
|
|
|
|
|
|
@ -180,7 +185,7 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0("Output does not exist! amount = " << tx_in_to_key.amount);
|
|
|
|
|
MERROR_VER("Output does not exist! amount = " << tx_in_to_key.amount);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -189,7 +194,7 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke
|
|
|
|
|
// check for partial results and add the rest if needed;
|
|
|
|
|
if (outputs.size() < absolute_offsets.size() && outputs.size() > 0)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Additional outputs needed: " << absolute_offsets.size() - outputs.size());
|
|
|
|
|
MDEBUG("Additional outputs needed: " << absolute_offsets.size() - outputs.size());
|
|
|
|
|
std::vector < uint64_t > add_offsets;
|
|
|
|
|
std::vector<output_data_t> add_outputs;
|
|
|
|
|
for (size_t i = outputs.size(); i < absolute_offsets.size(); i++)
|
|
|
|
@ -200,7 +205,7 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0("Output does not exist! amount = " << tx_in_to_key.amount);
|
|
|
|
|
MERROR_VER("Output does not exist! amount = " << tx_in_to_key.amount);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
outputs.insert(outputs.end(), add_outputs.begin(), add_outputs.end());
|
|
|
|
@ -224,13 +229,13 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke
|
|
|
|
|
// call to the passed boost visitor to grab the public key for the output
|
|
|
|
|
if (!vis.handle_output(output_index.unlock_time, output_index.pubkey, output_index.commitment))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0("Failed to handle_output for output no = " << count << ", with absolute offset " << i);
|
|
|
|
|
MERROR_VER("Failed to handle_output for output no = " << count << ", with absolute offset " << i);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0("Output does not exist! amount = " << tx_in_to_key.amount << ", absolute_offset = " << i);
|
|
|
|
|
MERROR_VER("Output does not exist! amount = " << tx_in_to_key.amount << ", absolute_offset = " << i);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -248,12 +253,12 @@ bool Blockchain::scan_outputkeys_for_indexes(size_t tx_version, const txin_to_ke
|
|
|
|
|
}
|
|
|
|
|
catch (const OUTPUT_DNE& e)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0("Output does not exist: " << e.what());
|
|
|
|
|
MERROR_VER("Output does not exist: " << e.what());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
catch (const TX_DNE& e)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0("Transaction does not exist: " << e.what());
|
|
|
|
|
MERROR_VER("Transaction does not exist: " << e.what());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -326,7 +331,7 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, const cryptonote::te
|
|
|
|
|
// taking testnet into account
|
|
|
|
|
if(!m_db->height())
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0("Blockchain not loaded, generating genesis block.");
|
|
|
|
|
MINFO("Blockchain not loaded, generating genesis block.");
|
|
|
|
|
block bl = boost::value_initialized<block>();
|
|
|
|
|
block_verification_context bvc = boost::value_initialized<block_verification_context>();
|
|
|
|
|
if (m_testnet)
|
|
|
|
@ -372,7 +377,7 @@ bool Blockchain::init(BlockchainDB* db, const bool testnet, const cryptonote::te
|
|
|
|
|
load_compiled_in_block_hashes();
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
LOG_PRINT_GREEN("Blockchain initialized. last block: " << m_db->height() - 1 << ", " << epee::misc_utils::get_time_interval_string(timestamp_diff) << " time ago, current difficulty: " << get_difficulty_for_next_block(), LOG_LEVEL_0);
|
|
|
|
|
MINFO("Blockchain initialized. last block: " << m_db->height() - 1 << ", " << epee::misc_utils::get_time_interval_string(timestamp_diff) << " time ago, current difficulty: " << get_difficulty_for_next_block());
|
|
|
|
|
m_db->block_txn_stop();
|
|
|
|
|
|
|
|
|
|
update_next_cumulative_size_limit();
|
|
|
|
@ -404,18 +409,18 @@ bool Blockchain::store_blockchain()
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0(std::string("Error syncing blockchain db: ") + e.what() + "-- shutting down now to prevent issues!");
|
|
|
|
|
MERROR(std::string("Error syncing blockchain db: ") + e.what() + "-- shutting down now to prevent issues!");
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0("There was an issue storing the blockchain, shutting down now to prevent issues!");
|
|
|
|
|
MERROR("There was an issue storing the blockchain, shutting down now to prevent issues!");
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TIME_MEASURE_FINISH(save);
|
|
|
|
|
if(m_show_time_stats)
|
|
|
|
|
LOG_PRINT_L0("Blockchain stored OK, took: " << save << " ms");
|
|
|
|
|
MINFO("Blockchain stored OK, took: " << save << " ms");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
@ -423,7 +428,7 @@ bool Blockchain::deinit()
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
|
|
|
|
|
|
|
|
|
LOG_PRINT_L1("Stopping blockchain read/write activity");
|
|
|
|
|
MTRACE("Stopping blockchain read/write activity");
|
|
|
|
|
|
|
|
|
|
// stop async service
|
|
|
|
|
m_async_work_idle.reset();
|
|
|
|
@ -441,7 +446,7 @@ bool Blockchain::deinit()
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
m_db->close();
|
|
|
|
|
LOG_PRINT_L1("Local blockchain read/write activity stopped successfully");
|
|
|
|
|
MTRACE("Local blockchain read/write activity stopped successfully");
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
@ -620,12 +625,12 @@ crypto::hash Blockchain::get_block_id_by_height(uint64_t height) const
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0(std::string("Something went wrong fetching block hash by height: ") + e.what());
|
|
|
|
|
MERROR(std::string("Something went wrong fetching block hash by height: ") + e.what());
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0(std::string("Something went wrong fetching block hash by height"));
|
|
|
|
|
MERROR(std::string("Something went wrong fetching block hash by height"));
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
return null_hash;
|
|
|
|
@ -654,12 +659,12 @@ bool Blockchain::get_block_by_hash(const crypto::hash &h, block &blk) const
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0(std::string("Something went wrong fetching block by hash: ") + e.what());
|
|
|
|
|
MERROR(std::string("Something went wrong fetching block by hash: ") + e.what());
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0(std::string("Something went wrong fetching block hash by hash"));
|
|
|
|
|
MERROR(std::string("Something went wrong fetching block hash by hash"));
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -773,10 +778,10 @@ bool Blockchain::rollback_blockchain_switching(std::list<block>& original_chain,
|
|
|
|
|
|
|
|
|
|
m_hardfork->reorganize_from_chain_height(rollback_height);
|
|
|
|
|
|
|
|
|
|
LOG_PRINT_L1("Rollback to height " << rollback_height << " was successful.");
|
|
|
|
|
MINFO("Rollback to height " << rollback_height << " was successful.");
|
|
|
|
|
if (original_chain.size())
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Restoration to previous blockchain successful as well.");
|
|
|
|
|
MINFO("Restoration to previous blockchain successful as well.");
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -824,7 +829,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::
|
|
|
|
|
// return false
|
|
|
|
|
if(!r || !bvc.m_added_to_main_chain)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to switch to alternative blockchain");
|
|
|
|
|
MERROR("Failed to switch to alternative blockchain");
|
|
|
|
|
|
|
|
|
|
// rollback_blockchain_switching should be moved to two different
|
|
|
|
|
// functions: rollback and apply_chain, but for now we pretend it is
|
|
|
|
@ -835,7 +840,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::
|
|
|
|
|
// about them again so we can immediately dismiss them, but needs some
|
|
|
|
|
// looking into.
|
|
|
|
|
add_block_as_invalid(ch_ent->second, get_block_hash(ch_ent->second.bl));
|
|
|
|
|
LOG_PRINT_L1("The block was inserted as invalid while connecting new alternative chain, block_id: " << get_block_hash(ch_ent->second.bl));
|
|
|
|
|
MERROR("The block was inserted as invalid while connecting new alternative chain, block_id: " << get_block_hash(ch_ent->second.bl));
|
|
|
|
|
m_alternative_chains.erase(*alt_ch_iter++);
|
|
|
|
|
|
|
|
|
|
for(auto alt_ch_to_orph_iter = alt_ch_iter; alt_ch_to_orph_iter != alt_chain.end(); )
|
|
|
|
@ -857,7 +862,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::
|
|
|
|
|
bool r = handle_alternative_block(old_ch_ent, get_block_hash(old_ch_ent), bvc);
|
|
|
|
|
if(!r)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to push ex-main chain blocks to alternative chain ");
|
|
|
|
|
MERROR("Failed to push ex-main chain blocks to alternative chain ");
|
|
|
|
|
// previously this would fail the blockchain switching, but I don't
|
|
|
|
|
// think this is bad enough to warrant that.
|
|
|
|
|
}
|
|
|
|
@ -872,7 +877,7 @@ bool Blockchain::switch_to_alternative_blockchain(std::list<blocks_ext_by_hash::
|
|
|
|
|
|
|
|
|
|
m_hardfork->reorganize_from_chain_height(split_height);
|
|
|
|
|
|
|
|
|
|
LOG_PRINT_GREEN("REORGANIZE SUCCESS! on height: " << split_height << ", new blockchain size: " << m_db->height(), LOG_LEVEL_0);
|
|
|
|
|
MGINFO_GREEN("REORGANIZE SUCCESS! on height: " << split_height << ", new blockchain size: " << m_db->height());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
@ -953,10 +958,10 @@ bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height)
|
|
|
|
|
CHECK_AND_ASSERT_MES(b.miner_tx.vin[0].type() == typeid(txin_gen), false, "coinbase transaction in the block has the wrong type");
|
|
|
|
|
if(boost::get<txin_gen>(b.miner_tx.vin[0]).height != height)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_RED_L1("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);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
LOG_PRINT_L1("Miner tx hash: " << get_transaction_hash(b.miner_tx));
|
|
|
|
|
MDEBUG("Miner tx hash: " << get_transaction_hash(b.miner_tx));
|
|
|
|
|
CHECK_AND_ASSERT_MES(b.miner_tx.unlock_time == height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW, false, "coinbase transaction transaction has the wrong unlock time=" << b.miner_tx.unlock_time << ", expected " << height + CRYPTONOTE_MINED_MONEY_UNLOCK_WINDOW);
|
|
|
|
|
|
|
|
|
|
//check outs overflow
|
|
|
|
@ -965,7 +970,7 @@ bool Blockchain::prevalidate_miner_transaction(const block& b, uint64_t height)
|
|
|
|
|
// does not overflow a uint64_t, and this transaction *is* a uint64_t...
|
|
|
|
|
if(!check_outs_overflow(b.miner_tx))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_RED_L1("miner transaction has money overflow in block " << get_block_hash(b));
|
|
|
|
|
MERROR("miner transaction has money overflow in block " << get_block_hash(b));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -985,7 +990,7 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
|
|
|
|
|
if (version == 3) {
|
|
|
|
|
for (auto &o: b.miner_tx.vout) {
|
|
|
|
|
if (!is_valid_decomposed_amount(o.amount)) {
|
|
|
|
|
LOG_PRINT_L1("miner tx output " << print_money(o.amount) << " is not a valid decomposed amount");
|
|
|
|
|
MERROR_VER("miner tx output " << print_money(o.amount) << " is not a valid decomposed amount");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -995,12 +1000,12 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
|
|
|
|
|
get_last_n_blocks_sizes(last_blocks_sizes, CRYPTONOTE_REWARD_BLOCKS_WINDOW);
|
|
|
|
|
if (!get_block_reward(epee::misc_utils::median(last_blocks_sizes), cumulative_block_size, already_generated_coins, base_reward, version))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("block size " << cumulative_block_size << " is bigger than allowed for this blockchain");
|
|
|
|
|
MERROR_VER("block size " << cumulative_block_size << " is bigger than allowed for this blockchain");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if(base_reward + fee < money_in_use)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("coinbase transaction spend too much money (" << print_money(money_in_use) << "). Block reward is " << print_money(base_reward + fee) << "(" << print_money(base_reward) << "+" << print_money(fee) << ")");
|
|
|
|
|
MERROR_VER("coinbase transaction spend too much money (" << print_money(money_in_use) << "). Block reward is " << print_money(base_reward + fee) << "(" << print_money(base_reward) << "+" << print_money(fee) << ")");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
// From hard fork 2, we allow a miner to claim less block reward than is allowed, in case a miner wants less dust
|
|
|
|
@ -1008,7 +1013,7 @@ bool Blockchain::validate_miner_transaction(const block& b, size_t cumulative_bl
|
|
|
|
|
{
|
|
|
|
|
if(base_reward + fee != money_in_use)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("coinbase transaction doesn't use full amount of block reward: spent: " << money_in_use << ", block reward " << base_reward + fee << "(" << base_reward << "+" << fee << ")");
|
|
|
|
|
MDEBUG("coinbase transaction doesn't use full amount of block reward: spent: " << money_in_use << ", block reward " << base_reward + fee << "(" << base_reward << "+" << fee << ")");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1139,7 +1144,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
|
|
|
|
|
LOG_ERROR("Creating block template: error: wrongly calculated fee");
|
|
|
|
|
}
|
|
|
|
|
CRITICAL_REGION_END();
|
|
|
|
|
LOG_PRINT_L1("Creating block template: height " << height <<
|
|
|
|
|
MDEBUG("Creating block template: height " << height <<
|
|
|
|
|
", median size " << median_size <<
|
|
|
|
|
", already generated coins " << already_generated_coins <<
|
|
|
|
|
", transaction size " << txs_size <<
|
|
|
|
@ -1157,7 +1162,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
|
|
|
|
|
CHECK_AND_ASSERT_MES(r, false, "Failed to construct miner tx, first chance");
|
|
|
|
|
size_t cumulative_size = txs_size + get_object_blobsize(b.miner_tx);
|
|
|
|
|
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
|
|
|
|
|
LOG_PRINT_L1("Creating block template: miner tx size " << get_object_blobsize(b.miner_tx) <<
|
|
|
|
|
MDEBUG("Creating block template: miner tx size " << get_object_blobsize(b.miner_tx) <<
|
|
|
|
|
", cumulative size " << cumulative_size);
|
|
|
|
|
#endif
|
|
|
|
|
for (size_t try_count = 0; try_count != 10; ++try_count)
|
|
|
|
@ -1170,7 +1175,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
|
|
|
|
|
{
|
|
|
|
|
cumulative_size = txs_size + coinbase_blob_size;
|
|
|
|
|
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
|
|
|
|
|
LOG_PRINT_L1("Creating block template: miner tx size " << coinbase_blob_size <<
|
|
|
|
|
MDEBUG("Creating block template: miner tx size " << coinbase_blob_size <<
|
|
|
|
|
", cumulative size " << cumulative_size << " is greater then before");
|
|
|
|
|
#endif
|
|
|
|
|
continue;
|
|
|
|
@ -1180,7 +1185,7 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
|
|
|
|
|
{
|
|
|
|
|
size_t delta = cumulative_size - txs_size - coinbase_blob_size;
|
|
|
|
|
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
|
|
|
|
|
LOG_PRINT_L1("Creating block template: miner tx size " << coinbase_blob_size <<
|
|
|
|
|
MDEBUG("Creating block template: miner tx size " << coinbase_blob_size <<
|
|
|
|
|
", cumulative size " << txs_size + coinbase_blob_size <<
|
|
|
|
|
" is less then before, adding " << delta << " zero bytes");
|
|
|
|
|
#endif
|
|
|
|
@ -1193,16 +1198,16 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m
|
|
|
|
|
if (cumulative_size != txs_size + get_object_blobsize(b.miner_tx))
|
|
|
|
|
{
|
|
|
|
|
//fuck, not lucky, -1 makes varint-counter size smaller, in that case we continue to grow with cumulative_size
|
|
|
|
|
LOG_PRINT_RED("Miner tx creation has no luck with delta_extra size = " << delta << " and " << delta - 1 , LOG_LEVEL_2);
|
|
|
|
|
MDEBUG("Miner tx creation has no luck with delta_extra size = " << delta << " and " << delta - 1);
|
|
|
|
|
cumulative_size += delta - 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
LOG_PRINT_GREEN("Setting extra for block: " << b.miner_tx.extra.size() << ", try_count=" << try_count, LOG_LEVEL_1);
|
|
|
|
|
MDEBUG("Setting extra for block: " << b.miner_tx.extra.size() << ", try_count=" << try_count);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
CHECK_AND_ASSERT_MES(cumulative_size == txs_size + get_object_blobsize(b.miner_tx), false, "unexpected case: cumulative_size=" << cumulative_size << " is not equal txs_cumulative_size=" << txs_size << " + get_object_blobsize(b.miner_tx)=" << get_object_blobsize(b.miner_tx));
|
|
|
|
|
#if defined(DEBUG_CREATE_BLOCK_TEMPLATE)
|
|
|
|
|
LOG_PRINT_L1("Creating block template: miner tx size " << coinbase_blob_size <<
|
|
|
|
|
MDEBUG("Creating block template: miner tx size " << coinbase_blob_size <<
|
|
|
|
|
", cumulative size " << cumulative_size << " is now good");
|
|
|
|
|
#endif
|
|
|
|
|
return true;
|
|
|
|
@ -1246,7 +1251,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
|
|
|
|
|
uint64_t block_height = get_block_height(b);
|
|
|
|
|
if(0 == block_height)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative), but miner tx says height is 0.");
|
|
|
|
|
MERROR_VER("Block with id: " << epee::string_tools::pod_to_hex(id) << " (as alternative), but miner tx says height is 0.");
|
|
|
|
|
bvc.m_verifivation_failed = true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@ -1256,7 +1261,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
|
|
|
|
|
// the block to be added, then this is fine.
|
|
|
|
|
if (!m_checkpoints.is_alternative_block_allowed(get_current_blockchain_height(), block_height))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_RED_L1("Block with id: " << id << std::endl << " can't be accepted for alternative chain, block height: " << block_height << std::endl << " blockchain height: " << get_current_blockchain_height());
|
|
|
|
|
MERROR_VER("Block with id: " << id << std::endl << " can't be accepted for alternative chain, block height: " << block_height << std::endl << " blockchain height: " << get_current_blockchain_height());
|
|
|
|
|
bvc.m_verifivation_failed = true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@ -1299,7 +1304,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
|
|
|
|
|
// this alternate chain with it.
|
|
|
|
|
if (!m_db->block_exists(alt_chain.front()->second.bl.prev_id))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("alternate chain does not appear to connect to main chain...");
|
|
|
|
|
MERROR("alternate chain does not appear to connect to main chain...");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1322,7 +1327,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
|
|
|
|
|
// (not earlier than the median of the last X blocks)
|
|
|
|
|
if(!check_block_timestamp(timestamps, b))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_RED_L1("Block with id: " << id << std::endl << " for alternative chain, has invalid timestamp: " << b.timestamp);
|
|
|
|
|
MERROR_VER("Block with id: " << id << std::endl << " for alternative chain, has invalid timestamp: " << b.timestamp);
|
|
|
|
|
bvc.m_verifivation_failed = true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@ -1348,14 +1353,14 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
|
|
|
|
|
get_block_longhash(bei.bl, proof_of_work, bei.height);
|
|
|
|
|
if(!check_hash(proof_of_work, current_diff))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_RED_L1("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);
|
|
|
|
|
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;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!prevalidate_miner_transaction(b, bei.height))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_RED_L1("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;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@ -1385,7 +1390,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
|
|
|
|
|
if(is_a_checkpoint)
|
|
|
|
|
{
|
|
|
|
|
//do reorganize!
|
|
|
|
|
LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_db->height() - 1 << ", checkpoint is found in alternative chain on height " << bei.height, LOG_LEVEL_0);
|
|
|
|
|
MGINFO_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_db->height() - 1 << ", checkpoint is found in alternative chain on height " << bei.height);
|
|
|
|
|
|
|
|
|
|
bool r = switch_to_alternative_blockchain(alt_chain, true);
|
|
|
|
|
|
|
|
|
@ -1397,7 +1402,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
|
|
|
|
|
else if(main_chain_cumulative_difficulty < bei.cumulative_difficulty) //check if difficulty bigger then in main chain
|
|
|
|
|
{
|
|
|
|
|
//do reorganize!
|
|
|
|
|
LOG_PRINT_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_db->height() - 1 << " with cum_difficulty " << m_db->get_block_cumulative_difficulty(m_db->height() - 1) << std::endl << " alternative blockchain size: " << alt_chain.size() << " with cum_difficulty " << bei.cumulative_difficulty, LOG_LEVEL_0);
|
|
|
|
|
MGINFO_GREEN("###### REORGANIZE on height: " << alt_chain.front()->second.height << " of " << m_db->height() - 1 << " with cum_difficulty " << m_db->get_block_cumulative_difficulty(m_db->height() - 1) << std::endl << " alternative blockchain size: " << alt_chain.size() << " with cum_difficulty " << bei.cumulative_difficulty);
|
|
|
|
|
|
|
|
|
|
bool r = switch_to_alternative_blockchain(alt_chain, false);
|
|
|
|
|
if (r)
|
|
|
|
@ -1408,7 +1413,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT " << bei.height << std::endl << "id:\t" << id << std::endl << "PoW:\t" << proof_of_work << std::endl << "difficulty:\t" << current_diff, LOG_LEVEL_0);
|
|
|
|
|
MGINFO_BLUE("----- BLOCK ADDED AS ALTERNATIVE ON HEIGHT " << bei.height << std::endl << "id:\t" << id << std::endl << "PoW:\t" << proof_of_work << std::endl << "difficulty:\t" << current_diff);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -1416,7 +1421,7 @@ bool Blockchain::handle_alternative_block(const block& b, const crypto::hash& id
|
|
|
|
|
{
|
|
|
|
|
//block orphaned
|
|
|
|
|
bvc.m_marked_as_orphaned = true;
|
|
|
|
|
LOG_PRINT_RED_L1("Block recognized as orphaned and rejected, id = " << id);
|
|
|
|
|
MERROR_VER("Block recognized as orphaned and rejected, id = " << id);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
@ -1805,7 +1810,7 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
|
|
|
|
|
// how can we expect to sync from the client that the block list came from?
|
|
|
|
|
if(!qblock_ids.size() /*|| !req.m_total_height*/)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Client sent wrong NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << qblock_ids.size() << /*", m_height=" << req.m_total_height <<*/ ", dropping connection");
|
|
|
|
|
MCERROR("net.p2p", "Client sent wrong NOTIFY_REQUEST_CHAIN: m_block_ids.size()=" << qblock_ids.size() << /*", m_height=" << req.m_total_height <<*/ ", dropping connection");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1815,7 +1820,7 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
|
|
|
|
|
auto gen_hash = m_db->get_block_hash_from_height(0);
|
|
|
|
|
if(qblock_ids.back() != gen_hash)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Client sent wrong NOTIFY_REQUEST_CHAIN: genesis block mismatch: " << std::endl << "id: " << qblock_ids.back() << ", " << std::endl << "expected: " << gen_hash << "," << std::endl << " dropping connection");
|
|
|
|
|
MCERROR("net.p2p", "Client sent wrong NOTIFY_REQUEST_CHAIN: genesis block mismatch: " << std::endl << "id: " << qblock_ids.back() << ", " << std::endl << "expected: " << gen_hash << "," << std::endl << " dropping connection");
|
|
|
|
|
m_db->block_txn_abort();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@ -1833,7 +1838,7 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Non-critical error trying to find block by hash in BlockchainDB, hash: " << *bl_it);
|
|
|
|
|
MWARNING("Non-critical error trying to find block by hash in BlockchainDB, hash: " << *bl_it);
|
|
|
|
|
m_db->block_txn_abort();
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@ -1844,7 +1849,7 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc
|
|
|
|
|
// but just in case...
|
|
|
|
|
if(bl_it == qblock_ids.end())
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Internal error handling connection, can't find split point");
|
|
|
|
|
MERROR("Internal error handling connection, can't find split point");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1863,7 +1868,7 @@ uint64_t Blockchain::block_difficulty(uint64_t i) const
|
|
|
|
|
}
|
|
|
|
|
catch (const BLOCK_DNE& e)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0("Attempted to get block difficulty for height above blockchain height");
|
|
|
|
|
MERROR("Attempted to get block difficulty for height above blockchain height");
|
|
|
|
|
}
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
@ -1928,7 +1933,7 @@ void Blockchain::print_blockchain(uint64_t start_index, uint64_t end_index) cons
|
|
|
|
|
auto h = m_db->height();
|
|
|
|
|
if(start_index > h)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Wrong starter index set: " << start_index << ", expected max index " << h);
|
|
|
|
|
MERROR("Wrong starter index set: " << start_index << ", expected max index " << h);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1936,8 +1941,7 @@ void Blockchain::print_blockchain(uint64_t start_index, uint64_t end_index) cons
|
|
|
|
|
{
|
|
|
|
|
ss << "height " << i << ", timestamp " << m_db->get_block_timestamp(i) << ", cumul_dif " << m_db->get_block_cumulative_difficulty(i) << ", size " << m_db->get_block_size(i) << "\nid\t\t" << m_db->get_block_hash_from_height(i) << "\ndifficulty\t\t" << m_db->get_block_difficulty(i) << ", nonce " << m_db->get_block_from_height(i).nonce << ", tx_count " << m_db->get_block_from_height(i).tx_hashes.size() << std::endl;
|
|
|
|
|
}
|
|
|
|
|
LOG_PRINT_L1("Current blockchain:" << std::endl << ss.str());
|
|
|
|
|
LOG_PRINT_L0("Blockchain printed with log level 1");
|
|
|
|
|
MCINFO("globlal", "Current blockchain:" << std::endl << ss.str());
|
|
|
|
|
}
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
void Blockchain::print_blockchain_index() const
|
|
|
|
@ -1954,7 +1958,7 @@ void Blockchain::print_blockchain_index() const
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
LOG_PRINT_L0("Current blockchain index:" << std::endl << ss.str());
|
|
|
|
|
MINFO("Current blockchain index:" << std::endl << ss.str());
|
|
|
|
|
}
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
//TODO: remove this function and references to it
|
|
|
|
@ -2041,7 +2045,7 @@ bool Blockchain::add_block_as_invalid(const block_extended_info& bei, const cryp
|
|
|
|
|
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
|
|
|
|
auto i_res = m_invalid_blocks.insert(std::map<crypto::hash, block_extended_info>::value_type(h, bei));
|
|
|
|
|
CHECK_AND_ASSERT_MES(i_res.second, false, "at insertion invalid by tx returned status existed");
|
|
|
|
|
LOG_PRINT_L1("BLOCK ADDED AS INVALID: " << h << std::endl << ", prev_id=" << bei.bl.prev_id << ", m_invalid_blocks count=" << m_invalid_blocks.size());
|
|
|
|
|
MINFO("BLOCK ADDED AS INVALID: " << h << std::endl << ", prev_id=" << bei.bl.prev_id << ", m_invalid_blocks count=" << m_invalid_blocks.size());
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
@ -2158,7 +2162,7 @@ bool Blockchain::get_tx_outputs_gindexs(const crypto::hash& tx_id, std::vector<u
|
|
|
|
|
uint64_t tx_index;
|
|
|
|
|
if (!m_db->tx_exists(tx_id, tx_index))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_RED_L1("warning: get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
|
|
|
|
|
MERROR_VER("get_tx_outputs_gindexs failed to find transaction with id = " << tx_id);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2200,7 +2204,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, uint64_t& max_used_block_heigh
|
|
|
|
|
if(m_show_time_stats)
|
|
|
|
|
{
|
|
|
|
|
size_t mixin = tx.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(tx.vin[0]).key_offsets.size() - 1 : 0;
|
|
|
|
|
LOG_PRINT_L0("HASH: " << "-" << " I/M/O: " << tx.vin.size() << "/" << mixin << "/" << tx.vout.size() << " H: " << 0 << " chcktx: " << a);
|
|
|
|
|
MINFO("HASH: " << "-" << " I/M/O: " << tx.vin.size() << "/" << mixin << "/" << tx.vout.size() << " H: " << 0 << " chcktx: " << a);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@ -2212,7 +2216,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, uint64_t& max_used_block_heigh
|
|
|
|
|
if(m_show_time_stats)
|
|
|
|
|
{
|
|
|
|
|
size_t mixin = tx.vin[0].type() == typeid(txin_to_key) ? boost::get<txin_to_key>(tx.vin[0]).key_offsets.size() - 1 : 0;
|
|
|
|
|
LOG_PRINT_L0("HASH: " << get_transaction_hash(tx) << " I/M/O: " << tx.vin.size() << "/" << mixin << "/" << tx.vout.size() << " H: " << max_used_block_height << " ms: " << a + m_fake_scan_time << " B: " << get_object_blobsize(tx));
|
|
|
|
|
MINFO("HASH: " << get_transaction_hash(tx) << " I/M/O: " << tx.vin.size() << "/" << mixin << "/" << tx.vout.size() << " H: " << max_used_block_height << " ms: " << a + m_fake_scan_time << " B: " << get_object_blobsize(tx));
|
|
|
|
|
}
|
|
|
|
|
if (!res)
|
|
|
|
|
return false;
|
|
|
|
@ -2388,7 +2392,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
uint64_t n_outputs = m_db->get_num_outputs(in_to_key.amount);
|
|
|
|
|
LOG_PRINT_L2("output size " << print_money(in_to_key.amount) << ": " << n_outputs << " available");
|
|
|
|
|
MDEBUG("output size " << print_money(in_to_key.amount) << ": " << n_outputs << " available");
|
|
|
|
|
// n_outputs includes the output we're considering
|
|
|
|
|
if (n_outputs <= min_mixin)
|
|
|
|
|
++n_unmixable;
|
|
|
|
@ -2404,13 +2408,13 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
{
|
|
|
|
|
if (n_unmixable == 0)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Tx " << get_transaction_hash(tx) << " has too low mixin (" << mixin << "), and no unmixable inputs");
|
|
|
|
|
MERROR_VER("Tx " << get_transaction_hash(tx) << " has too low mixin (" << mixin << "), and no unmixable inputs");
|
|
|
|
|
tvc.m_low_mixin = true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (n_mixable > 1)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Tx " << get_transaction_hash(tx) << " has too low mixin (" << mixin << "), and more than one mixable input with unmixable inputs");
|
|
|
|
|
MERROR_VER("Tx " << get_transaction_hash(tx) << " has too low mixin (" << mixin << "), and more than one mixable input with unmixable inputs");
|
|
|
|
|
tvc.m_low_mixin = true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@ -2420,14 +2424,14 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
const size_t max_tx_version = (hf_version <= 3) ? 1 : 2;
|
|
|
|
|
if (tx.version > max_tx_version)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("transaction version " << (unsigned)tx.version << " is higher than max accepted version " << max_tx_version);
|
|
|
|
|
MERROR_VER("transaction version " << (unsigned)tx.version << " is higher than max accepted version " << max_tx_version);
|
|
|
|
|
tvc.m_verifivation_failed = true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
const size_t min_tx_version = (n_unmixable > 0 ? 1 : (hf_version >= 5) ? 2 : 1);
|
|
|
|
|
if (tx.version < min_tx_version)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("transaction version " << (unsigned)tx.version << " is lower than min accepted version " << min_tx_version);
|
|
|
|
|
MERROR_VER("transaction version " << (unsigned)tx.version << " is lower than min accepted version " << min_tx_version);
|
|
|
|
|
tvc.m_verifivation_failed = true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@ -2486,7 +2490,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
|
|
|
|
|
if(have_tx_keyimg_as_spent(in_to_key.k_image))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Key image already spent in blockchain: " << epee::string_tools::pod_to_hex(in_to_key.k_image));
|
|
|
|
|
MERROR_VER("Key image already spent in blockchain: " << epee::string_tools::pod_to_hex(in_to_key.k_image));
|
|
|
|
|
tvc.m_double_spend = true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
@ -2502,7 +2506,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
{
|
|
|
|
|
if(!itk->second)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index);
|
|
|
|
|
MERROR_VER("Failed ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2518,10 +2522,10 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
if (!check_tx_input(tx.version, in_to_key, tx_prefix_hash, tx.version == 1 ? tx.signatures[sig_index] : std::vector<crypto::signature>(), tx.rct_signatures, pubkeys[sig_index], pmax_used_block_height))
|
|
|
|
|
{
|
|
|
|
|
it->second[in_to_key.k_image] = false;
|
|
|
|
|
LOG_PRINT_L1("Failed to check ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index);
|
|
|
|
|
MERROR_VER("Failed to check ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index);
|
|
|
|
|
if (pmax_used_block_height) // a default value of NULL is used when called from Blockchain::handle_block_to_main_chain()
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1(" *pmax_used_block_height: " << *pmax_used_block_height);
|
|
|
|
|
MERROR_VER(" *pmax_used_block_height: " << *pmax_used_block_height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
@ -2541,11 +2545,11 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
if (!results[sig_index])
|
|
|
|
|
{
|
|
|
|
|
it->second[in_to_key.k_image] = false;
|
|
|
|
|
LOG_PRINT_L1("Failed to check ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index);
|
|
|
|
|
MERROR_VER("Failed to check ring signature for tx " << get_transaction_hash(tx) << " vin key with k_image: " << in_to_key.k_image << " sig_index: " << sig_index);
|
|
|
|
|
|
|
|
|
|
if (pmax_used_block_height) // a default value of NULL is used when called from Blockchain::handle_block_to_main_chain()
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("*pmax_used_block_height: " << *pmax_used_block_height);
|
|
|
|
|
MERROR_VER("*pmax_used_block_height: " << *pmax_used_block_height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
@ -2575,7 +2579,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
|
|
|
|
|
if (failed)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to check ring signatures!, t_loop: " << t_t1);
|
|
|
|
|
MERROR_VER("Failed to check ring signatures!, t_loop: " << t_t1);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2584,7 +2588,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
{
|
|
|
|
|
if (!expand_transaction_2(tx, tx_prefix_hash, pubkeys))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to expand rct signatures!");
|
|
|
|
|
MERROR_VER("Failed to expand rct signatures!");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2596,7 +2600,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
{
|
|
|
|
|
case rct::RCTTypeNull: {
|
|
|
|
|
// we only accept no signatures for coinbase txes
|
|
|
|
|
LOG_PRINT_L1("Null rct signature on non-coinbase tx");
|
|
|
|
|
MERROR_VER("Null rct signature on non-coinbase tx");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
case rct::RCTTypeSimple: {
|
|
|
|
@ -2604,14 +2608,14 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
{
|
|
|
|
|
if (pubkeys.size() != rv.mixRing.size())
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to check ringct signatures: mismatched pubkeys/mixRing size");
|
|
|
|
|
MERROR_VER("Failed to check ringct signatures: mismatched pubkeys/mixRing size");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
for (size_t i = 0; i < pubkeys.size(); ++i)
|
|
|
|
|
{
|
|
|
|
|
if (pubkeys[i].size() != rv.mixRing[i].size())
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to check ringct signatures: mismatched pubkeys/mixRing size");
|
|
|
|
|
MERROR_VER("Failed to check ringct signatures: mismatched pubkeys/mixRing size");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2622,12 +2626,12 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
{
|
|
|
|
|
if (pubkeys[n][m].dest != rct::rct2pk(rv.mixRing[n][m].dest))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to check ringct signatures: mismatched pubkey at vin " << n << ", index " << m);
|
|
|
|
|
MERROR_VER("Failed to check ringct signatures: mismatched pubkey at vin " << n << ", index " << m);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (pubkeys[n][m].mask != rct::rct2pk(rv.mixRing[n][m].mask))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to check ringct signatures: mismatched commitment at vin " << n << ", index " << m);
|
|
|
|
|
MERROR_VER("Failed to check ringct signatures: mismatched commitment at vin " << n << ", index " << m);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2636,21 +2640,21 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
|
|
|
|
|
if (rv.p.MGs.size() != tx.vin.size())
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to check ringct signatures: mismatched MGs/vin sizes");
|
|
|
|
|
MERROR_VER("Failed to check ringct signatures: mismatched MGs/vin sizes");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
for (size_t n = 0; n < tx.vin.size(); ++n)
|
|
|
|
|
{
|
|
|
|
|
if (memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.MGs[n].II[0], 32))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to check ringct signatures: mismatched key image");
|
|
|
|
|
MERROR_VER("Failed to check ringct signatures: mismatched key image");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!rct::verRctSimple(rv, false))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to check ringct signatures!");
|
|
|
|
|
MERROR_VER("Failed to check ringct signatures!");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
@ -2665,7 +2669,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
size_matches &= pubkeys.size() == rv.mixRing[i].size();
|
|
|
|
|
if (!size_matches)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to check ringct signatures: mismatched pubkeys/mixRing size");
|
|
|
|
|
MERROR_VER("Failed to check ringct signatures: mismatched pubkeys/mixRing size");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2675,12 +2679,12 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
{
|
|
|
|
|
if (pubkeys[n][m].dest != rct::rct2pk(rv.mixRing[m][n].dest))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to check ringct signatures: mismatched pubkey at vin " << n << ", index " << m);
|
|
|
|
|
MERROR_VER("Failed to check ringct signatures: mismatched pubkey at vin " << n << ", index " << m);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (pubkeys[n][m].mask != rct::rct2pk(rv.mixRing[m][n].mask))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to check ringct signatures: mismatched commitment at vin " << n << ", index " << m);
|
|
|
|
|
MERROR_VER("Failed to check ringct signatures: mismatched commitment at vin " << n << ", index " << m);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2689,32 +2693,32 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc,
|
|
|
|
|
|
|
|
|
|
if (rv.p.MGs.size() != 1)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to check ringct signatures: Bad MGs size");
|
|
|
|
|
MERROR_VER("Failed to check ringct signatures: Bad MGs size");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (rv.p.MGs[0].II.size() != tx.vin.size())
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to check ringct signatures: mismatched II/vin sizes");
|
|
|
|
|
MERROR_VER("Failed to check ringct signatures: mismatched II/vin sizes");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
for (size_t n = 0; n < tx.vin.size(); ++n)
|
|
|
|
|
{
|
|
|
|
|
if (memcmp(&boost::get<txin_to_key>(tx.vin[n]).k_image, &rv.p.MGs[0].II[n], 32))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to check ringct signatures: mismatched II/vin sizes");
|
|
|
|
|
MERROR_VER("Failed to check ringct signatures: mismatched II/vin sizes");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!rct::verRct(rv, false))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to check ringct signatures!");
|
|
|
|
|
MERROR_VER("Failed to check ringct signatures!");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
LOG_PRINT_L1("Unsupported rct type: " << rv.type);
|
|
|
|
|
MERROR_VER("Unsupported rct type: " << rv.type);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2777,7 +2781,7 @@ bool Blockchain::check_fee(size_t blob_size, uint64_t fee) const
|
|
|
|
|
return false;
|
|
|
|
|
fee_per_kb = get_dynamic_per_kb_fee(base_reward, median);
|
|
|
|
|
}
|
|
|
|
|
LOG_PRINT_L2("Using " << print_money(fee) << "/kB fee");
|
|
|
|
|
MDEBUG("Using " << print_money(fee) << "/kB fee");
|
|
|
|
|
|
|
|
|
|
uint64_t needed_fee = blob_size / 1024;
|
|
|
|
|
needed_fee += (blob_size % 1024) ? 1 : 0;
|
|
|
|
@ -2785,7 +2789,7 @@ bool Blockchain::check_fee(size_t blob_size, uint64_t fee) const
|
|
|
|
|
|
|
|
|
|
if (fee < needed_fee)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("transaction fee is not enough: " << print_money(fee) << ", minimum fee: " << print_money(needed_fee));
|
|
|
|
|
MERROR_VER("transaction fee is not enough: " << print_money(fee) << ", minimum fee: " << print_money(needed_fee));
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
@ -2815,12 +2819,12 @@ uint64_t Blockchain::get_dynamic_per_kb_fee_estimate(uint64_t grace_blocks) cons
|
|
|
|
|
uint64_t base_reward;
|
|
|
|
|
if (!get_block_reward(median, 1, already_generated_coins, base_reward, version))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to determine block reward, using placeholder " << print_money(BLOCK_REWARD_OVERESTIMATE) << " as a high bound");
|
|
|
|
|
MERROR("Failed to determine block reward, using placeholder " << print_money(BLOCK_REWARD_OVERESTIMATE) << " as a high bound");
|
|
|
|
|
base_reward = BLOCK_REWARD_OVERESTIMATE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
uint64_t fee = get_dynamic_per_kb_fee(base_reward, median);
|
|
|
|
|
LOG_PRINT_L2("Estimating " << grace_blocks << "-block fee at " << print_money(fee) << "/kB");
|
|
|
|
|
MDEBUG("Estimating " << grace_blocks << "-block fee at " << print_money(fee) << "/kB");
|
|
|
|
|
return fee;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2875,7 +2879,7 @@ bool Blockchain::check_tx_input(size_t tx_version, const txin_to_key& txin, cons
|
|
|
|
|
//check tx unlock time
|
|
|
|
|
if (!m_bch.is_tx_spendtime_unlocked(unlock_time))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("One of outputs for one of inputs has wrong tx.unlock_time = " << unlock_time);
|
|
|
|
|
MERROR_VER("One of outputs for one of inputs has wrong tx.unlock_time = " << unlock_time);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2895,13 +2899,13 @@ bool Blockchain::check_tx_input(size_t tx_version, const txin_to_key& txin, cons
|
|
|
|
|
outputs_visitor vi(output_keys, *this);
|
|
|
|
|
if (!scan_outputkeys_for_indexes(tx_version, txin, vi, tx_prefix_hash, pmax_related_block_height))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Failed to get output keys for tx with amount = " << print_money(txin.amount) << " and count indexes " << txin.key_offsets.size());
|
|
|
|
|
MERROR_VER("Failed to get output keys for tx with amount = " << print_money(txin.amount) << " and count indexes " << txin.key_offsets.size());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(txin.key_offsets.size() != output_keys.size())
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Output keys for tx with amount = " << txin.amount << " and count indexes " << txin.key_offsets.size() << " returned wrong keys count " << output_keys.size());
|
|
|
|
|
MERROR_VER("Output keys for tx with amount = " << txin.amount << " and count indexes " << txin.key_offsets.size() << " returned wrong keys count " << output_keys.size());
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (tx_version == 1) {
|
|
|
|
@ -2927,7 +2931,7 @@ bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const
|
|
|
|
|
|
|
|
|
|
if(b.timestamp < median_ts)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", less than median of last " << BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW << " blocks, " << median_ts);
|
|
|
|
|
MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", less than median of last " << BLOCKCHAIN_TIMESTAMP_CHECK_WINDOW << " blocks, " << median_ts);
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2946,7 +2950,7 @@ bool Blockchain::check_block_timestamp(const block& b) const
|
|
|
|
|
LOG_PRINT_L3("Blockchain::" << __func__);
|
|
|
|
|
if(b.timestamp > get_adjusted_time() + CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than adjusted time + 2 hours");
|
|
|
|
|
MERROR_VER("Timestamp of block with id: " << get_block_hash(b) << ", " << b.timestamp << ", bigger than adjusted time + 2 hours");
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -2982,7 +2986,7 @@ void Blockchain::return_tx_to_pool(const std::vector<transaction> &txs)
|
|
|
|
|
// all the transactions in a popped block when a reorg happens.
|
|
|
|
|
if (!m_tx_pool.add_tx(tx, tvc, true, true, false, version))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0("Failed to return taken transaction with hash: " << get_transaction_hash(tx) << " to tx_pool");
|
|
|
|
|
MERROR("Failed to return taken transaction with hash: " << get_transaction_hash(tx) << " to tx_pool");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -2998,10 +3002,10 @@ bool Blockchain::flush_txes_from_pool(const std::list<crypto::hash> &txids)
|
|
|
|
|
size_t blob_size;
|
|
|
|
|
uint64_t fee;
|
|
|
|
|
bool relayed, do_not_relay;
|
|
|
|
|
LOG_PRINT_L1("Removing txid " << txid << " from the pool");
|
|
|
|
|
MINFO("Removing txid " << txid << " from the pool");
|
|
|
|
|
if(m_tx_pool.have_tx(txid) && !m_tx_pool.take_tx(txid, tx, blob_size, fee, relayed, do_not_relay))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0("Failed to remove txid " << txid << " from the pool");
|
|
|
|
|
MERROR("Failed to remove txid " << txid << " from the pool");
|
|
|
|
|
res = false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -3022,7 +3026,7 @@ bool Blockchain::handle_block_to_main_chain(const block& bl, const crypto::hash&
|
|
|
|
|
m_db->block_txn_start(true);
|
|
|
|
|
if(bl.prev_id != get_tail_id())
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Block with id: " << id << std::endl << "has wrong prev_id: " << bl.prev_id << std::endl << "expected: " << get_tail_id());
|
|
|
|
|
MERROR_VER("Block with id: " << id << std::endl << "has wrong prev_id: " << bl.prev_id << std::endl << "expected: " << get_tail_id());
|
|
|
|
|
leave:
|
|
|
|
|
m_db->block_txn_stop();
|
|
|
|
|
return false;
|
|
|
|
@ -3031,7 +3035,7 @@ leave:
|
|
|
|
|
// this is a cheap test
|
|
|
|
|
if (!m_hardfork->check(bl))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("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)m_hardfork->get_current_version());
|
|
|
|
|
bvc.m_verifivation_failed = true;
|
|
|
|
|
goto leave;
|
|
|
|
|
}
|
|
|
|
@ -3043,7 +3047,7 @@ leave:
|
|
|
|
|
// of a set number of the most recent blocks.
|
|
|
|
|
if(!check_block_timestamp(bl))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Block with id: " << id << std::endl << "has invalid timestamp: " << bl.timestamp);
|
|
|
|
|
MERROR_VER("Block with id: " << id << std::endl << "has invalid timestamp: " << bl.timestamp);
|
|
|
|
|
bvc.m_verifivation_failed = true;
|
|
|
|
|
goto leave;
|
|
|
|
|
}
|
|
|
|
@ -3083,7 +3087,7 @@ leave:
|
|
|
|
|
auto hash = get_block_hash(bl);
|
|
|
|
|
if (memcmp(&hash, &m_blocks_hash_check[m_db->height()], sizeof(hash)) != 0)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Block with id is INVALID: " << id);
|
|
|
|
|
MERROR_VER("Block with id is INVALID: " << id);
|
|
|
|
|
bvc.m_verifivation_failed = true;
|
|
|
|
|
goto leave;
|
|
|
|
|
}
|
|
|
|
@ -3104,7 +3108,7 @@ leave:
|
|
|
|
|
// validate proof_of_work versus difficulty target
|
|
|
|
|
if(!check_hash(proof_of_work, current_diffic))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Block with id: " << id << std::endl << "does not have enough proof of work: " << proof_of_work << std::endl << "unexpected difficulty: " << current_diffic);
|
|
|
|
|
MERROR_VER("Block with id: " << id << std::endl << "does not have enough proof of work: " << proof_of_work << std::endl << "unexpected difficulty: " << current_diffic);
|
|
|
|
|
bvc.m_verifivation_failed = true;
|
|
|
|
|
goto leave;
|
|
|
|
|
}
|
|
|
|
@ -3131,7 +3135,7 @@ leave:
|
|
|
|
|
// sanity check basic miner tx properties;
|
|
|
|
|
if(!prevalidate_miner_transaction(bl, m_db->height()))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Block with id: " << id << " failed to pass prevalidation");
|
|
|
|
|
MERROR_VER("Block with id: " << id << " failed to pass prevalidation");
|
|
|
|
|
bvc.m_verifivation_failed = true;
|
|
|
|
|
goto leave;
|
|
|
|
|
}
|
|
|
|
@ -3166,7 +3170,7 @@ leave:
|
|
|
|
|
// XXX old code does not check whether tx exists
|
|
|
|
|
if (m_db->tx_exists(tx_id))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Block with id: " << id << " attempting to add transaction already in blockchain with id: " << tx_id);
|
|
|
|
|
MERROR("Block with id: " << id << " attempting to add transaction already in blockchain with id: " << tx_id);
|
|
|
|
|
bvc.m_verifivation_failed = true;
|
|
|
|
|
return_tx_to_pool(txs);
|
|
|
|
|
goto leave;
|
|
|
|
@ -3179,7 +3183,7 @@ leave:
|
|
|
|
|
// get transaction with hash <tx_id> from tx_pool
|
|
|
|
|
if(!m_tx_pool.take_tx(tx_id, tx, blob_size, fee, relayed, do_not_relay))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Block with id: " << id << " has at least one unknown transaction with id: " << tx_id);
|
|
|
|
|
MERROR_VER("Block with id: " << id << " has at least one unknown transaction with id: " << tx_id);
|
|
|
|
|
bvc.m_verifivation_failed = true;
|
|
|
|
|
return_tx_to_pool(txs);
|
|
|
|
|
goto leave;
|
|
|
|
@ -3218,11 +3222,11 @@ leave:
|
|
|
|
|
tx_verification_context tvc;
|
|
|
|
|
if(!check_tx_inputs(tx, tvc))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs.");
|
|
|
|
|
MERROR_VER("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs.");
|
|
|
|
|
|
|
|
|
|
//TODO: why is this done? make sure that keeping invalid blocks makes sense.
|
|
|
|
|
add_block_as_invalid(bl, id);
|
|
|
|
|
LOG_PRINT_L1("Block with id " << id << " added as invalid because of wrong inputs in transactions");
|
|
|
|
|
MERROR_VER("Block with id " << id << " added as invalid because of wrong inputs in transactions");
|
|
|
|
|
bvc.m_verifivation_failed = true;
|
|
|
|
|
return_tx_to_pool(txs);
|
|
|
|
|
goto leave;
|
|
|
|
@ -3235,10 +3239,10 @@ leave:
|
|
|
|
|
// the transaction inputs, but do some sanity checks anyway.
|
|
|
|
|
if (memcmp(&m_blocks_txs_check[tx_index++], &tx_id, sizeof(tx_id)) != 0)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs.");
|
|
|
|
|
MERROR_VER("Block with id: " << id << " has at least one transaction (id: " << tx_id << ") with wrong inputs.");
|
|
|
|
|
//TODO: why is this done? make sure that keeping invalid blocks makes sense.
|
|
|
|
|
add_block_as_invalid(bl, id);
|
|
|
|
|
LOG_PRINT_L1("Block with id " << id << " added as invalid because of wrong inputs in transactions");
|
|
|
|
|
MERROR_VER("Block with id " << id << " added as invalid because of wrong inputs in transactions");
|
|
|
|
|
bvc.m_verifivation_failed = true;
|
|
|
|
|
return_tx_to_pool(txs);
|
|
|
|
|
goto leave;
|
|
|
|
@ -3258,7 +3262,7 @@ leave:
|
|
|
|
|
uint64_t already_generated_coins = m_db->height() ? m_db->get_block_already_generated_coins(m_db->height() - 1) : 0;
|
|
|
|
|
if(!validate_miner_transaction(bl, cumulative_block_size, fee_summary, base_reward, already_generated_coins, bvc.m_partial_block_reward, m_hardfork->get_current_version()))
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Block with id: " << id << " has incorrect miner transaction");
|
|
|
|
|
MERROR_VER("Block with id: " << id << " has incorrect miner transaction");
|
|
|
|
|
bvc.m_verifivation_failed = true;
|
|
|
|
|
return_tx_to_pool(txs);
|
|
|
|
|
goto leave;
|
|
|
|
@ -3317,10 +3321,10 @@ leave:
|
|
|
|
|
// do this after updating the hard fork state since the size limit may change due to fork
|
|
|
|
|
update_next_cumulative_size_limit();
|
|
|
|
|
|
|
|
|
|
LOG_PRINT_L1("+++++ BLOCK SUCCESSFULLY ADDED" << std::endl << "id:\t" << id << std::endl << "PoW:\t" << proof_of_work << std::endl << "HEIGHT " << new_height-1 << ", difficulty:\t" << current_diffic << std::endl << "block reward: " << print_money(fee_summary + base_reward) << "(" << print_money(base_reward) << " + " << print_money(fee_summary) << "), coinbase_blob_size: " << coinbase_blob_size << ", cumulative size: " << cumulative_block_size << ", " << block_processing_time << "(" << target_calculating_time << "/" << longhash_calculating_time << ")ms");
|
|
|
|
|
MINFO("+++++ BLOCK SUCCESSFULLY ADDED" << std::endl << "id:\t" << id << std::endl << "PoW:\t" << proof_of_work << std::endl << "HEIGHT " << new_height-1 << ", difficulty:\t" << current_diffic << std::endl << "block reward: " << print_money(fee_summary + base_reward) << "(" << print_money(base_reward) << " + " << print_money(fee_summary) << "), coinbase_blob_size: " << coinbase_blob_size << ", cumulative size: " << cumulative_block_size << ", " << block_processing_time << "(" << target_calculating_time << "/" << longhash_calculating_time << ")ms");
|
|
|
|
|
if(m_show_time_stats)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0("Height: " << new_height << " blob: " << coinbase_blob_size << " cumm: "
|
|
|
|
|
MINFO("Height: " << new_height << " blob: " << coinbase_blob_size << " cumm: "
|
|
|
|
|
<< cumulative_block_size << " p/t: " << block_processing_time << " ("
|
|
|
|
|
<< target_calculating_time << "/" << longhash_calculating_time << "/"
|
|
|
|
|
<< t1 << "/" << t2 << "/" << t3 << "/" << t_exists << "/" << t_pool
|
|
|
|
@ -3448,7 +3452,7 @@ bool Blockchain::update_checkpoints(const std::string& file_path, bool check_dns
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0("One or more checkpoints fetched from DNS conflicted with existing checkpoints!");
|
|
|
|
|
MERROR("One or more checkpoints fetched from DNS conflicted with existing checkpoints!");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -3486,7 +3490,7 @@ void Blockchain::block_longhash_worker(const uint64_t height, const std::vector<
|
|
|
|
|
//------------------------------------------------------------------
|
|
|
|
|
bool Blockchain::cleanup_handle_incoming_blocks(bool force_sync)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_YELLOW("Blockchain::" << __func__, LOG_LEVEL_3);
|
|
|
|
|
MTRACE("Blockchain::" << __func__);
|
|
|
|
|
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
|
|
|
|
TIME_MEASURE_START(t1);
|
|
|
|
|
|
|
|
|
@ -3536,7 +3540,7 @@ void Blockchain::output_scan_worker(const uint64_t amount, const std::vector<uin
|
|
|
|
|
}
|
|
|
|
|
catch (const std::exception& e)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("EXCEPTION: " << e.what());
|
|
|
|
|
MERROR_VER("EXCEPTION: " << e.what());
|
|
|
|
|
}
|
|
|
|
|
catch (...)
|
|
|
|
|
{
|
|
|
|
@ -3553,7 +3557,7 @@ void Blockchain::output_scan_worker(const uint64_t amount, const std::vector<uin
|
|
|
|
|
// keys.
|
|
|
|
|
bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_entry> &blocks_entry)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_YELLOW("Blockchain::" << __func__, LOG_LEVEL_3);
|
|
|
|
|
MTRACE("Blockchain::" << __func__);
|
|
|
|
|
TIME_MEASURE_START(prepare);
|
|
|
|
|
bool stop_batch;
|
|
|
|
|
CRITICAL_REGION_LOCAL(m_blockchain_lock);
|
|
|
|
@ -3583,7 +3587,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_e
|
|
|
|
|
std::vector<boost::thread *> thread_list;
|
|
|
|
|
int batches = blocks_entry.size() / threads;
|
|
|
|
|
int extra = blocks_entry.size() % threads;
|
|
|
|
|
LOG_PRINT_L1("block_batches: " << batches);
|
|
|
|
|
MDEBUG("block_batches: " << batches);
|
|
|
|
|
std::vector<std::unordered_map<crypto::hash, crypto::hash>> maps(threads);
|
|
|
|
|
std::vector < std::vector < block >> blocks(threads);
|
|
|
|
|
auto it = blocks_entry.begin();
|
|
|
|
@ -3606,7 +3610,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_e
|
|
|
|
|
crypto::hash tophash = m_db->top_block_hash();
|
|
|
|
|
if (block.prev_id != tophash)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L1("Skipping prepare blocks. New blocks don't belong to chain.");
|
|
|
|
|
MDEBUG("Skipping prepare blocks. New blocks don't belong to chain.");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -3672,7 +3676,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_e
|
|
|
|
|
|
|
|
|
|
if (blocks_exist)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0("Skipping prepare blocks. Blocks exist.");
|
|
|
|
|
MDEBUG("Skipping prepare blocks. Blocks exist.");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -3686,7 +3690,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_e
|
|
|
|
|
m_fake_pow_calc_time = prepare / blocks_entry.size();
|
|
|
|
|
|
|
|
|
|
if (blocks_entry.size() > 1 && threads > 1 && m_show_time_stats)
|
|
|
|
|
LOG_PRINT_L0("Prepare blocks took: " << prepare << " ms");
|
|
|
|
|
MDEBUG("Prepare blocks took: " << prepare << " ms");
|
|
|
|
|
|
|
|
|
|
TIME_MEASURE_START(scantable);
|
|
|
|
|
|
|
|
|
@ -3699,7 +3703,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_e
|
|
|
|
|
|
|
|
|
|
#define SCAN_TABLE_QUIT(m) \
|
|
|
|
|
do { \
|
|
|
|
|
LOG_PRINT_L0(m) ;\
|
|
|
|
|
MERROR_VER(m) ;\
|
|
|
|
|
m_scan_table.clear(); \
|
|
|
|
|
return false; \
|
|
|
|
|
} while(0); \
|
|
|
|
@ -3873,7 +3877,7 @@ bool Blockchain::prepare_handle_incoming_blocks(const std::list<block_complete_e
|
|
|
|
|
{
|
|
|
|
|
m_fake_scan_time = scantable / total_txs;
|
|
|
|
|
if(m_show_time_stats)
|
|
|
|
|
LOG_PRINT_L0("Prepare scantable took: " << scantable << " ms");
|
|
|
|
|
MDEBUG("Prepare scantable took: " << scantable << " ms");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
@ -3951,7 +3955,7 @@ void Blockchain::load_compiled_in_block_hashes()
|
|
|
|
|
const size_t size_needed = 4 + nblocks * sizeof(crypto::hash);
|
|
|
|
|
if(nblocks > 0 && nblocks > m_db->height() && get_blocks_dat_size(m_testnet) >= size_needed)
|
|
|
|
|
{
|
|
|
|
|
LOG_PRINT_L0("Loading precomputed blocks: " << nblocks);
|
|
|
|
|
MINFO("Loading precomputed blocks: " << nblocks);
|
|
|
|
|
p += sizeof(uint32_t);
|
|
|
|
|
for (uint32_t i = 0; i < nblocks; i++)
|
|
|
|
|
{
|
|
|
|
|