diff options
Diffstat (limited to 'src/cryptonote_core')
-rw-r--r-- | src/cryptonote_core/blockchain.cpp | 51 | ||||
-rw-r--r-- | src/cryptonote_core/blockchain.h | 7 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_core.cpp | 12 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_core.h | 10 | ||||
-rw-r--r-- | src/cryptonote_core/tx_pool.cpp | 43 | ||||
-rw-r--r-- | src/cryptonote_core/tx_pool.h | 4 |
6 files changed, 87 insertions, 40 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index 83b9da895..0448551c4 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -807,16 +807,18 @@ difficulty_type Blockchain::get_difficulty_for_next_block() { LOG_PRINT_L3("Blockchain::" << __func__); - CRITICAL_REGION_LOCAL(m_difficulty_lock); - // we can call this without the blockchain lock, it might just give us - // something a bit out of date, but that's fine since anything which - // requires the blockchain lock will have acquired it in the first place, - // and it will be unlocked only when called from the getinfo RPC crypto::hash top_hash = get_tail_id(); - if (top_hash == m_difficulty_for_next_block_top_hash) - return m_difficulty_for_next_block; + { + CRITICAL_REGION_LOCAL(m_difficulty_lock); + // we can call this without the blockchain lock, it might just give us + // something a bit out of date, but that's fine since anything which + // requires the blockchain lock will have acquired it in the first place, + // and it will be unlocked only when called from the getinfo RPC + if (top_hash == m_difficulty_for_next_block_top_hash) + return m_difficulty_for_next_block; + } - CRITICAL_REGION_LOCAL1(m_blockchain_lock); + CRITICAL_REGION_LOCAL(m_blockchain_lock); std::vector<uint64_t> timestamps; std::vector<difficulty_type> difficulties; auto height = m_db->height(); @@ -825,7 +827,7 @@ difficulty_type Blockchain::get_difficulty_for_next_block() // then when the next block difficulty is queried, push the latest height data and // pop the oldest one from the list. This only requires 1x read per height instead // of doing 735 (DIFFICULTY_BLOCKS_COUNT). - if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1)) + if (m_timestamps_and_difficulties_height != 0 && ((height - m_timestamps_and_difficulties_height) == 1) && m_timestamps.size() >= DIFFICULTY_BLOCKS_COUNT) { uint64_t index = height - 1; m_timestamps.push_back(m_db->get_block_timestamp(index)); @@ -860,6 +862,8 @@ difficulty_type Blockchain::get_difficulty_for_next_block() } size_t target = get_difficulty_target(); difficulty_type diff = next_difficulty(timestamps, difficulties, target); + + CRITICAL_REGION_LOCAL1(m_difficulty_lock); m_difficulty_for_next_block_top_hash = top_hash; m_difficulty_for_next_block = diff; return diff; @@ -2098,16 +2102,19 @@ bool Blockchain::get_blocks(const t_ids_container& block_ids, t_blocks_container { try { - blocks.push_back(std::make_pair(m_db->get_block_blob(block_hash), block())); - if (!parse_and_validate_block_from_blob(blocks.back().first, blocks.back().second)) + uint64_t height = 0; + if (m_db->block_exists(block_hash, &height)) { - LOG_ERROR("Invalid block"); - return false; + blocks.push_back(std::make_pair(m_db->get_block_blob_from_height(height), block())); + if (!parse_and_validate_block_from_blob(blocks.back().first, blocks.back().second)) + { + LOG_ERROR("Invalid block: " << block_hash); + blocks.pop_back(); + missed_bs.push_back(block_hash); + } } - } - catch (const BLOCK_DNE& e) - { - missed_bs.push_back(block_hash); + else + missed_bs.push_back(block_hash); } catch (const std::exception& e) { @@ -2285,19 +2292,19 @@ bool Blockchain::have_block(const crypto::hash& id) const if(m_db->block_exists(id)) { - LOG_PRINT_L3("block exists in main chain"); + LOG_PRINT_L2("block " << id << " found in main chain"); return true; } if(m_alternative_chains.count(id)) { - LOG_PRINT_L3("block found in m_alternative_chains"); + LOG_PRINT_L2("block " << id << " found in m_alternative_chains"); return true; } if(m_invalid_blocks.count(id)) { - LOG_PRINT_L3("block found in m_invalid_blocks"); + LOG_PRINT_L2("block " << id << " found in m_invalid_blocks"); return true; } @@ -3936,7 +3943,7 @@ uint64_t Blockchain::prevalidate_block_hashes(uint64_t height, const std::list<c // add to the known hashes array if (!valid) { - MWARNING("invalid hash for blocks " << n * HASH_OF_HASHES_STEP << " - " << (n * HASH_OF_HASHES_STEP + HASH_OF_HASHES_STEP - 1)); + MDEBUG("invalid hash for blocks " << n * HASH_OF_HASHES_STEP << " - " << (n * HASH_OF_HASHES_STEP + HASH_OF_HASHES_STEP - 1)); break; } @@ -4434,7 +4441,7 @@ void Blockchain::cancel() } #if defined(PER_BLOCK_CHECKPOINT) -static const char expected_block_hashes_hash[] = "59261c03b54bcb21bd463f9fe40a94f40840a12642e9a3b3bfb11b35839a5fe3"; +static const char expected_block_hashes_hash[] = "0924bc1c47aae448321fde949554be192878dd800e6489379865218f84eacbca"; void Blockchain::load_compiled_in_block_hashes() { const bool testnet = m_nettype == TESTNET; diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index 769e608ca..ef736d1e7 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -795,6 +795,13 @@ namespace cryptonote uint8_t get_hard_fork_version(uint64_t height) const { return m_hardfork->get(height); } /** + * @brief returns the earliest block a given version may activate + * + * @return the height + */ + uint64_t get_earliest_ideal_height_for_version(uint8_t version) const { return m_hardfork->get_earliest_ideal_height_for_version(version); } + + /** * @brief get information about hardfork voting for a version * * @param version the version in question diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index d2796deeb..7fc81a87d 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -170,7 +170,6 @@ namespace cryptonote m_last_dns_checkpoints_update(0), m_last_json_checkpoints_update(0), m_disable_dns_checkpoints(false), - m_threadpool(tools::threadpool::getInstance()), m_update_download(0), m_nettype(UNDEFINED) { @@ -676,15 +675,17 @@ namespace cryptonote bool core::handle_incoming_txs(const std::list<blobdata>& tx_blobs, std::vector<tx_verification_context>& tvc, bool keeped_by_block, bool relayed, bool do_not_relay) { TRY_ENTRY(); + CRITICAL_REGION_LOCAL(m_incoming_tx_lock); struct result { bool res; cryptonote::transaction tx; crypto::hash hash; crypto::hash prefix_hash; bool in_txpool; bool in_blockchain; }; std::vector<result> results(tx_blobs.size()); tvc.resize(tx_blobs.size()); + tools::threadpool& tpool = tools::threadpool::getInstance(); tools::threadpool::waiter waiter; std::list<blobdata>::const_iterator it = tx_blobs.begin(); for (size_t i = 0; i < tx_blobs.size(); i++, ++it) { - m_threadpool.submit(&waiter, [&, i, it] { + tpool.submit(&waiter, [&, i, it] { try { results[i].res = handle_incoming_tx_pre(*it, tvc[i], results[i].tx, results[i].hash, results[i].prefix_hash, keeped_by_block, relayed, do_not_relay); @@ -711,7 +712,7 @@ namespace cryptonote } else { - m_threadpool.submit(&waiter, [&, i, it] { + tpool.submit(&waiter, [&, i, it] { try { results[i].res = handle_incoming_tx_post(*it, tvc[i], results[i].tx, results[i].hash, results[i].prefix_hash, keeped_by_block, relayed, do_not_relay); @@ -1401,6 +1402,11 @@ namespace cryptonote return get_blockchain_storage().get_hard_fork_version(height); } //----------------------------------------------------------------------------------------------- + uint64_t core::get_earliest_ideal_height_for_version(uint8_t version) const + { + return get_blockchain_storage().get_earliest_ideal_height_for_version(version); + } + //----------------------------------------------------------------------------------------------- bool core::check_updates() { static const char software[] = "monero"; diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index 17b5680e5..91bd50729 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -39,7 +39,6 @@ #include "cryptonote_protocol/cryptonote_protocol_handler_common.h" #include "storages/portable_storage_template_helper.h" #include "common/download.h" -#include "common/threadpool.h" #include "common/command_line.h" #include "tx_pool.h" #include "blockchain.h" @@ -663,6 +662,13 @@ namespace cryptonote uint8_t get_hard_fork_version(uint64_t height) const; /** + * @brief return the earliest block a given version may activate + * + * @return what it says above + */ + uint64_t get_earliest_ideal_height_for_version(uint8_t version) const; + + /** * @brief gets start_time * */ @@ -984,8 +990,6 @@ namespace cryptonote std::unordered_set<crypto::hash> bad_semantics_txes[2]; boost::mutex bad_semantics_txes_lock; - tools::threadpool& m_threadpool; - enum { UPDATES_DISABLED, UPDATES_NOTIFY, diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index bf1fe476e..164530b3e 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -927,8 +927,26 @@ namespace cryptonote m_transactions_lock.unlock(); } //--------------------------------------------------------------------------------- - bool tx_memory_pool::is_transaction_ready_to_go(txpool_tx_meta_t& txd, transaction &tx) const + bool tx_memory_pool::is_transaction_ready_to_go(txpool_tx_meta_t& txd, const cryptonote::blobdata &txblob, transaction &tx) const { + struct transction_parser + { + transction_parser(const cryptonote::blobdata &txblob, transaction &tx): txblob(txblob), tx(tx), parsed(false) {} + cryptonote::transaction &operator()() + { + if (!parsed) + { + if (!parse_and_validate_tx_from_blob(txblob, tx)) + throw std::runtime_error("failed to parse transaction blob"); + parsed = true; + } + return tx; + } + const cryptonote::blobdata &txblob; + transaction &tx; + bool parsed; + } lazy_tx(txblob, tx); + //not the best implementation at this time, sorry :( //check is ring_signature already checked ? if(txd.max_used_block_id == null_hash) @@ -938,7 +956,7 @@ namespace cryptonote return false;//we already sure that this tx is broken for this height tx_verification_context tvc; - if(!m_blockchain.check_tx_inputs(tx, txd.max_used_block_height, txd.max_used_block_id, tvc)) + if(!m_blockchain.check_tx_inputs(lazy_tx(), txd.max_used_block_height, txd.max_used_block_id, tvc)) { txd.last_failed_height = m_blockchain.get_current_blockchain_height()-1; txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height); @@ -955,7 +973,7 @@ namespace cryptonote return false; //check ring signature again, it is possible (with very small chance) that this transaction become again valid tx_verification_context tvc; - if(!m_blockchain.check_tx_inputs(tx, txd.max_used_block_height, txd.max_used_block_id, tvc)) + if(!m_blockchain.check_tx_inputs(lazy_tx(), txd.max_used_block_height, txd.max_used_block_id, tvc)) { txd.last_failed_height = m_blockchain.get_current_blockchain_height()-1; txd.last_failed_id = m_blockchain.get_block_id_by_height(txd.last_failed_height); @@ -964,7 +982,7 @@ namespace cryptonote } } //if we here, transaction seems valid, but, anyway, check for key_images collisions with blockchain, just to be sure - if(m_blockchain.have_tx_keyimges_as_spent(tx)) + if(m_blockchain.have_tx_keyimges_as_spent(lazy_tx())) { txd.double_spend_seen = true; return false; @@ -1140,18 +1158,21 @@ namespace cryptonote cryptonote::blobdata txblob = m_blockchain.get_txpool_tx_blob(sorted_it->second); cryptonote::transaction tx; - if (!parse_and_validate_tx_from_blob(txblob, tx)) - { - MERROR("Failed to parse tx from txpool"); - sorted_it++; - continue; - } // Skip transactions that are not ready to be // included into the blockchain or that are // missing key images const cryptonote::txpool_tx_meta_t original_meta = meta; - bool ready = is_transaction_ready_to_go(meta, tx); + bool ready = false; + try + { + ready = is_transaction_ready_to_go(meta, txblob, tx); + } + catch (const std::exception &e) + { + MERROR("Failed to check transaction readiness: " << e.what()); + // continue, not fatal + } if (memcmp(&original_meta, &meta, sizeof(meta))) { try diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h index 19cd83ed9..4ce2f085d 100644 --- a/src/cryptonote_core/tx_pool.h +++ b/src/cryptonote_core/tx_pool.h @@ -499,10 +499,12 @@ namespace cryptonote * @brief check if a transaction is a valid candidate for inclusion in a block * * @param txd the transaction to check (and info about it) + * @param txblob the transaction blob to check + * @param tx the parsed transaction, if successful * * @return true if the transaction is good to go, otherwise false */ - bool is_transaction_ready_to_go(txpool_tx_meta_t& txd, transaction &tx) const; + bool is_transaction_ready_to_go(txpool_tx_meta_t& txd, const cryptonote::blobdata &txblob, transaction &tx) const; /** * @brief mark all transactions double spending the one passed |