aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_core')
-rw-r--r--src/cryptonote_core/blockchain.cpp51
-rw-r--r--src/cryptonote_core/blockchain.h7
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp12
-rw-r--r--src/cryptonote_core/cryptonote_core.h10
-rw-r--r--src/cryptonote_core/tx_pool.cpp43
-rw-r--r--src/cryptonote_core/tx_pool.h4
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