diff options
Diffstat (limited to 'src/cryptonote_core')
-rw-r--r-- | src/cryptonote_core/blockchain.cpp | 53 | ||||
-rw-r--r-- | src/cryptonote_core/blockchain.h | 20 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_core.cpp | 15 | ||||
-rw-r--r-- | src/cryptonote_core/cryptonote_core.h | 2 | ||||
-rw-r--r-- | src/cryptonote_core/tx_pool.cpp | 4 |
5 files changed, 63 insertions, 31 deletions
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index d1ef7d6fe..54d8fac31 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -156,7 +156,9 @@ static const struct { //------------------------------------------------------------------ Blockchain::Blockchain(tx_memory_pool& tx_pool) : m_db(), m_tx_pool(tx_pool), m_hardfork(NULL), m_timestamps_and_difficulties_height(0), m_current_block_cumul_sz_limit(0), m_current_block_cumul_sz_median(0), - m_enforce_dns_checkpoints(false), m_max_prepare_blocks_threads(4), m_db_blocks_per_sync(1), m_db_sync_mode(db_async), m_db_default_sync(false), m_fast_sync(true), m_show_time_stats(false), m_sync_counter(0), m_cancel(false) + m_enforce_dns_checkpoints(false), m_max_prepare_blocks_threads(4), m_db_blocks_per_sync(1), m_db_sync_mode(db_async), m_db_default_sync(false), m_fast_sync(true), m_show_time_stats(false), m_sync_counter(0), m_cancel(false), + m_difficulty_for_next_block_top_hash(crypto::null_hash), + m_difficulty_for_next_block(1) { LOG_PRINT_L3("Blockchain::" << __func__); } @@ -804,7 +806,17 @@ bool Blockchain::get_block_by_hash(const crypto::hash &h, block &blk, bool *orph difficulty_type Blockchain::get_difficulty_for_next_block() { LOG_PRINT_L3("Blockchain::" << __func__); - CRITICAL_REGION_LOCAL(m_blockchain_lock); + + 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_LOCAL1(m_blockchain_lock); std::vector<uint64_t> timestamps; std::vector<difficulty_type> difficulties; auto height = m_db->height(); @@ -847,7 +859,10 @@ difficulty_type Blockchain::get_difficulty_for_next_block() m_difficulties = difficulties; } size_t target = get_difficulty_target(); - return next_difficulty(timestamps, difficulties, target); + difficulty_type diff = next_difficulty(timestamps, difficulties, target); + m_difficulty_for_next_block_top_hash = top_hash; + m_difficulty_for_next_block = diff; + return diff; } //------------------------------------------------------------------ // This function removes blocks from the blockchain until it gets to the @@ -1195,6 +1210,12 @@ bool Blockchain::create_block_template(block& b, const account_public_address& m b.prev_id = get_tail_id(); b.timestamp = time(NULL); + uint64_t median_ts; + if (!check_block_timestamp(b, median_ts)) + { + b.timestamp = median_ts; + } + diffic = get_difficulty_for_next_block(); CHECK_AND_ASSERT_MES(diffic, false, "difficulty overhead."); @@ -2092,7 +2113,7 @@ bool Blockchain::get_blocks(const t_ids_container& block_ids, t_blocks_container //TODO: return type should be void, throw on exception // alternatively, return true only if no transactions missed template<class t_ids_container, class t_tx_container, class t_missed_container> -bool Blockchain::get_transactions_blobs(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const +bool Blockchain::get_transactions_blobs(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs, bool pruned) const { LOG_PRINT_L3("Blockchain::" << __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); @@ -2102,7 +2123,9 @@ bool Blockchain::get_transactions_blobs(const t_ids_container& txs_ids, t_tx_con try { cryptonote::blobdata tx; - if (m_db->get_tx_blob(tx_hash, tx)) + if (pruned && m_db->get_pruned_tx_blob(tx_hash, tx)) + txs.push_back(std::move(tx)); + else if (!pruned && m_db->get_tx_blob(tx_hash, tx)) txs.push_back(std::move(tx)); else missed_txs.push_back(tx_hash); @@ -2187,7 +2210,7 @@ bool Blockchain::find_blockchain_supplement(const std::list<crypto::hash>& qbloc // find split point between ours and foreign blockchain (or start at // blockchain height <req_start_block>), and return up to max_count FULL // blocks by reference. -bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::list<std::pair<cryptonote::blobdata, std::list<cryptonote::blobdata> > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count) const +bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::list<std::pair<cryptonote::blobdata, std::list<cryptonote::blobdata> > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, size_t max_count) const { LOG_PRINT_L3("Blockchain::" << __func__); CRITICAL_REGION_LOCAL(m_blockchain_lock); @@ -2220,7 +2243,7 @@ bool Blockchain::find_blockchain_supplement(const uint64_t req_start_block, cons block b; CHECK_AND_ASSERT_MES(parse_and_validate_block_from_blob(blocks.back().first, b), false, "internal error, invalid block"); std::list<crypto::hash> mis; - get_transactions_blobs(b.tx_hashes, blocks.back().second, mis); + get_transactions_blobs(b.tx_hashes, blocks.back().second, mis, pruned); CHECK_AND_ASSERT_MES(!mis.size(), false, "internal error, transaction from block not found"); size += blocks.back().first.size(); for (const auto &t: blocks.back().second) @@ -2696,6 +2719,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, tools::threadpool& tpool = tools::threadpool::getInstance(); tools::threadpool::waiter waiter; + const auto waiter_guard = epee::misc_utils::create_scope_leave_handler([&]() { waiter.wait(); }); int threads = tpool.get_max_concurrency(); for (const auto& txin : tx.vin) @@ -3165,10 +3189,10 @@ uint64_t Blockchain::get_adjusted_time() const } //------------------------------------------------------------------ //TODO: revisit, has changed a bit on upstream -bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const block& b) const +bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const block& b, uint64_t& median_ts) const { LOG_PRINT_L3("Blockchain::" << __func__); - uint64_t median_ts = epee::misc_utils::median(timestamps); + median_ts = epee::misc_utils::median(timestamps); if(b.timestamp < median_ts) { @@ -3186,7 +3210,7 @@ bool Blockchain::check_block_timestamp(std::vector<uint64_t>& timestamps, const // true if the block's timestamp is not less than the timestamp of the // median of the selected blocks // false otherwise -bool Blockchain::check_block_timestamp(const block& b) const +bool Blockchain::check_block_timestamp(const block& b, uint64_t& median_ts) const { LOG_PRINT_L3("Blockchain::" << __func__); if(b.timestamp > get_adjusted_time() + CRYPTONOTE_BLOCK_FUTURE_TIME_LIMIT) @@ -3211,7 +3235,7 @@ bool Blockchain::check_block_timestamp(const block& b) const timestamps.push_back(m_db->get_block_timestamp(offset)); } - return check_block_timestamp(timestamps, b); + return check_block_timestamp(timestamps, b, median_ts); } //------------------------------------------------------------------ void Blockchain::return_tx_to_pool(std::vector<transaction> &txs) @@ -4403,7 +4427,7 @@ void Blockchain::cancel() } #if defined(PER_BLOCK_CHECKPOINT) -static const char expected_block_hashes_hash[] = "1d3df1a177bd6f752d87c0d7b960e502605742721afb39953265f1e0f7f9b01f"; +static const char expected_block_hashes_hash[] = "59261c03b54bcb21bd463f9fe40a94f40840a12642e9a3b3bfb11b35839a5fe3"; void Blockchain::load_compiled_in_block_hashes() { const bool testnet = m_nettype == TESTNET; @@ -4514,9 +4538,9 @@ bool Blockchain::for_blocks_range(const uint64_t& h1, const uint64_t& h2, std::f return m_db->for_blocks_range(h1, h2, f); } -bool Blockchain::for_all_transactions(std::function<bool(const crypto::hash&, const cryptonote::transaction&)> f) const +bool Blockchain::for_all_transactions(std::function<bool(const crypto::hash&, const cryptonote::transaction&)> f, bool pruned) const { - return m_db->for_all_transactions(f); + return m_db->for_all_transactions(f, pruned); } bool Blockchain::for_all_outputs(std::function<bool(uint64_t amount, const crypto::hash &tx_hash, uint64_t height, size_t tx_idx)> f) const @@ -4531,4 +4555,5 @@ bool Blockchain::for_all_outputs(uint64_t amount, std::function<bool(uint64_t he namespace cryptonote { template bool Blockchain::get_transactions(const std::vector<crypto::hash>&, std::list<transaction>&, std::list<crypto::hash>&) const; +template bool Blockchain::get_transactions_blobs(const std::vector<crypto::hash>&, std::list<cryptonote::blobdata>&, std::list<crypto::hash>&, bool) const; } diff --git a/src/cryptonote_core/blockchain.h b/src/cryptonote_core/blockchain.h index f58885812..769e608ca 100644 --- a/src/cryptonote_core/blockchain.h +++ b/src/cryptonote_core/blockchain.h @@ -415,11 +415,12 @@ namespace cryptonote * @param blocks return-by-reference the blocks and their transactions * @param total_height return-by-reference our current blockchain height * @param start_height return-by-reference the height of the first block returned + * @param pruned whether to return full or pruned tx blobs * @param max_count the max number of blocks to get * * @return true if a block found in common or req_start_block specified, else false */ - bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::list<std::pair<cryptonote::blobdata, std::list<cryptonote::blobdata> > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count) const; + bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::list<std::pair<cryptonote::blobdata, std::list<cryptonote::blobdata> > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, size_t max_count) const; /** * @brief retrieves a set of blocks and their transactions, and possibly other transactions @@ -679,11 +680,12 @@ namespace cryptonote * @param txs_ids a container of hashes for which to get the corresponding transactions * @param txs return-by-reference a container to store result transactions in * @param missed_txs return-by-reference a container to store missed transactions in + * @param pruned whether to return full or pruned blobs * * @return false if an unexpected exception occurs, else true */ template<class t_ids_container, class t_tx_container, class t_missed_container> - bool get_transactions_blobs(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const; + bool get_transactions_blobs(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs, bool pruned = false) const; template<class t_ids_container, class t_tx_container, class t_missed_container> bool get_transactions(const t_ids_container& txs_ids, t_tx_container& txs, t_missed_container& missed_txs) const; @@ -858,10 +860,11 @@ namespace cryptonote * @brief perform a check on all transactions in the blockchain * * @param std::function the check to perform, pass/fail + * @param bool pruned whether to return pruned txes only * * @return false if any transaction fails the check, otherwise true */ - bool for_all_transactions(std::function<bool(const crypto::hash&, const cryptonote::transaction&)>) const; + bool for_all_transactions(std::function<bool(const crypto::hash&, const cryptonote::transaction&)>, bool pruned) const; /** * @brief perform a check on all outputs in the blockchain @@ -1008,6 +1011,10 @@ namespace cryptonote std::vector<difficulty_type> m_difficulties; uint64_t m_timestamps_and_difficulties_height; + epee::critical_section m_difficulty_lock; + crypto::hash m_difficulty_for_next_block_top_hash; + difficulty_type m_difficulty_for_next_block; + boost::asio::io_service m_async_service; boost::thread_group m_async_pool; std::unique_ptr<boost::asio::io_service::work> m_async_work_idle; @@ -1293,10 +1300,12 @@ namespace cryptonote * false otherwise * * @param b the block to be checked + * @param median_ts return-by-reference the median of timestamps * * @return true if the block's timestamp is valid, otherwise false */ - bool check_block_timestamp(const block& b) const; + bool check_block_timestamp(const block& b, uint64_t& median_ts) const; + bool check_block_timestamp(const block& b) const { uint64_t median_ts; return check_block_timestamp(b, median_ts); } /** * @brief checks a block's timestamp @@ -1309,7 +1318,8 @@ namespace cryptonote * * @return true if the block's timestamp is valid, otherwise false */ - bool check_block_timestamp(std::vector<uint64_t>& timestamps, const block& b) const; + bool check_block_timestamp(std::vector<uint64_t>& timestamps, const block& b, uint64_t& median_ts) const; + bool check_block_timestamp(std::vector<uint64_t>& timestamps, const block& b) const { uint64_t median_ts; return check_block_timestamp(timestamps, b, median_ts); } /** * @brief get the "adjusted time" diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp index 01cd56a11..d2796deeb 100644 --- a/src/cryptonote_core/cryptonote_core.cpp +++ b/src/cryptonote_core/cryptonote_core.cpp @@ -438,6 +438,7 @@ namespace cryptonote std::vector<std::string> options; boost::trim(db_sync_mode); boost::split(options, db_sync_mode, boost::is_any_of(" :")); + const bool db_sync_mode_is_default = command_line::is_arg_defaulted(vm, cryptonote::arg_db_sync_mode); for(const auto &option : options) MDEBUG("option: " << option); @@ -458,18 +459,18 @@ namespace cryptonote { safemode = true; db_flags = DBF_SAFE; - sync_mode = db_nosync; + sync_mode = db_sync_mode_is_default ? db_defaultsync : db_nosync; } else if(options[0] == "fast") { db_flags = DBF_FAST; - sync_mode = db_async; + sync_mode = db_sync_mode_is_default ? db_defaultsync : db_async; } else if(options[0] == "fastest") { db_flags = DBF_FASTEST; blocks_per_sync = 1000; // default to fastest:async:1000 - sync_mode = db_async; + sync_mode = db_sync_mode_is_default ? db_defaultsync : db_async; } else db_flags = DEFAULT_FLAGS; @@ -478,9 +479,9 @@ namespace cryptonote if(options.size() >= 2 && !safemode) { if(options[1] == "sync") - sync_mode = db_sync; + sync_mode = db_sync_mode_is_default ? db_defaultsync : db_sync; else if(options[1] == "async") - sync_mode = db_async; + sync_mode = db_sync_mode_is_default ? db_defaultsync : db_async; } if(options.size() >= 3 && !safemode) @@ -1053,9 +1054,9 @@ namespace cryptonote return m_blockchain_storage.find_blockchain_supplement(qblock_ids, resp); } //----------------------------------------------------------------------------------------------- - bool core::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::list<std::pair<cryptonote::blobdata, std::list<cryptonote::blobdata> > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count) const + bool core::find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::list<std::pair<cryptonote::blobdata, std::list<cryptonote::blobdata> > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, size_t max_count) const { - return m_blockchain_storage.find_blockchain_supplement(req_start_block, qblock_ids, blocks, total_height, start_height, max_count); + return m_blockchain_storage.find_blockchain_supplement(req_start_block, qblock_ids, blocks, total_height, start_height, pruned, max_count); } //----------------------------------------------------------------------------------------------- bool core::get_random_outs_for_amounts(const COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::request& req, COMMAND_RPC_GET_RANDOM_OUTPUTS_FOR_AMOUNTS::response& res) const diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h index f3b9dddc0..17b5680e5 100644 --- a/src/cryptonote_core/cryptonote_core.h +++ b/src/cryptonote_core/cryptonote_core.h @@ -517,7 +517,7 @@ namespace cryptonote * * @note see Blockchain::find_blockchain_supplement(const uint64_t, const std::list<crypto::hash>&, std::list<std::pair<cryptonote::blobdata, std::list<transaction> > >&, uint64_t&, uint64_t&, size_t) const */ - bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::list<std::pair<cryptonote::blobdata, std::list<cryptonote::blobdata> > >& blocks, uint64_t& total_height, uint64_t& start_height, size_t max_count) const; + bool find_blockchain_supplement(const uint64_t req_start_block, const std::list<crypto::hash>& qblock_ids, std::list<std::pair<cryptonote::blobdata, std::list<cryptonote::blobdata> > >& blocks, uint64_t& total_height, uint64_t& start_height, bool pruned, size_t max_count) const; /** * @brief gets some stats about the daemon diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp index 5dfbc1dd4..bf1fe476e 100644 --- a/src/cryptonote_core/tx_pool.cpp +++ b/src/cryptonote_core/tx_pool.cpp @@ -1068,10 +1068,6 @@ namespace cryptonote //TODO: investigate whether boolean return is appropriate bool tx_memory_pool::fill_block_template(block &bl, size_t median_size, uint64_t already_generated_coins, size_t &total_size, uint64_t &fee, uint64_t &expected_reward, uint8_t version) { - // Warning: This function takes already_generated_ - // coins as an argument and appears to do nothing - // with it. - CRITICAL_REGION_LOCAL(m_transactions_lock); CRITICAL_REGION_LOCAL1(m_blockchain); |