aboutsummaryrefslogtreecommitdiff
path: root/src/cryptonote_core
diff options
context:
space:
mode:
Diffstat (limited to 'src/cryptonote_core')
-rw-r--r--src/cryptonote_core/blockchain.cpp48
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp7
-rw-r--r--src/cryptonote_core/cryptonote_core.h3
-rw-r--r--src/cryptonote_core/tx_pool.cpp45
-rw-r--r--src/cryptonote_core/tx_pool.h4
5 files changed, 70 insertions, 37 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index 76a26a8f4..78f61766f 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -444,7 +444,7 @@ bool Blockchain::init(BlockchainDB* db, const network_type nettype, bool offline
m_db->block_txn_stop();
uint64_t num_popped_blocks = 0;
- while (true)
+ while (!m_db->is_read_only())
{
const uint64_t top_height = m_db->height() - 1;
const crypto::hash top_id = m_db->top_block_hash();
@@ -827,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));
@@ -1960,14 +1960,21 @@ bool Blockchain::get_outs(const COMMAND_RPC_GET_OUTPUTS_BIN::request& req, COMMA
res.outs.clear();
res.outs.reserve(req.outputs.size());
- for (const auto &i: req.outputs)
+ try
{
- // get tx_hash, tx_out_index from DB
- const output_data_t od = m_db->get_output_key(i.amount, i.index);
- tx_out_index toi = m_db->get_output_tx_and_index(i.amount, i.index);
- bool unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first));
+ for (const auto &i: req.outputs)
+ {
+ // get tx_hash, tx_out_index from DB
+ const output_data_t od = m_db->get_output_key(i.amount, i.index);
+ tx_out_index toi = m_db->get_output_tx_and_index(i.amount, i.index);
+ bool unlocked = is_tx_spendtime_unlocked(m_db->get_tx_unlock_time(toi.first));
- res.outs.push_back({od.pubkey, od.commitment, unlocked, od.height, toi.first});
+ res.outs.push_back({od.pubkey, od.commitment, unlocked, od.height, toi.first});
+ }
+ }
+ catch (const std::exception &e)
+ {
+ return false;
}
return true;
}
@@ -2095,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)
{
@@ -2282,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;
}
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index 7d34415c4..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);
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 567966d48..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"
@@ -991,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..9df3b458b 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -239,6 +239,7 @@ namespace cryptonote
meta.relayed = relayed;
meta.do_not_relay = do_not_relay;
meta.double_spend_seen = have_tx_keyimges_as_spent(tx);
+ meta.bf_padding = 0;
memset(meta.padding, 0, sizeof(meta.padding));
try
{
@@ -278,6 +279,7 @@ namespace cryptonote
meta.relayed = relayed;
meta.do_not_relay = do_not_relay;
meta.double_spend_seen = false;
+ meta.bf_padding = 0;
memset(meta.padding, 0, sizeof(meta.padding));
try
@@ -927,8 +929,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 +958,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 +975,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 +984,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 +1160,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