diff options
Diffstat (limited to 'src/blockchain_db')
-rw-r--r-- | src/blockchain_db/CMakeLists.txt | 2 | ||||
-rw-r--r-- | src/blockchain_db/blockchain_db.cpp | 2 | ||||
-rw-r--r-- | src/blockchain_db/blockchain_db.h | 12 | ||||
-rw-r--r-- | src/blockchain_db/lmdb/db_lmdb.cpp | 71 | ||||
-rw-r--r-- | src/blockchain_db/lmdb/db_lmdb.h | 5 | ||||
-rw-r--r-- | src/blockchain_db/locked_txn.h | 2 | ||||
-rw-r--r-- | src/blockchain_db/testdb.h | 7 |
7 files changed, 91 insertions, 10 deletions
diff --git a/src/blockchain_db/CMakeLists.txt b/src/blockchain_db/CMakeLists.txt index 0a21e4920..77faade17 100644 --- a/src/blockchain_db/CMakeLists.txt +++ b/src/blockchain_db/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2019, The Monero Project +# Copyright (c) 2014-2020, The Monero Project # # All rights reserved. # diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp index 336577a07..5c8dece2a 100644 --- a/src/blockchain_db/blockchain_db.cpp +++ b/src/blockchain_db/blockchain_db.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2014-2020, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index ac2c55db1..9a321437b 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2014-2020, The Monero Project // // All rights reserved. // @@ -1040,6 +1040,16 @@ public: virtual difficulty_type get_block_difficulty(const uint64_t& height) const = 0; /** + * @brief correct blocks cumulative difficulties that were incorrectly calculated due to the 'difficulty drift' bug + * + * If the block does not exist, the subclass should throw BLOCK_DNE + * + * @param start_height the height where the drift starts + * @param new_cumulative_difficulties new cumulative difficulties to be stored + */ + virtual void correct_block_cumulative_difficulties(const uint64_t& start_height, const std::vector<difficulty_type>& new_cumulative_difficulties) = 0; + + /** * @brief fetch a block's already generated coins * * The subclass should return the total coins generated as of the block diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 5cec8879d..6ea55d09d 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2014-2020, The Monero Project // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are @@ -25,6 +25,13 @@ // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +#ifndef _WIN32 +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/mman.h> +#include <fcntl.h> +#endif + #include "db_lmdb.h" #include <boost/filesystem.hpp> @@ -1287,6 +1294,26 @@ BlockchainLMDB::BlockchainLMDB(bool batch_transactions): BlockchainDB() m_hardfork = nullptr; } +void BlockchainLMDB::check_mmap_support() +{ +#ifndef _WIN32 + const boost::filesystem::path mmap_test_file = m_folder / boost::filesystem::unique_path(); + int mmap_test_fd = ::open(mmap_test_file.string().c_str(), O_RDWR | O_CREAT, 0600); + if (mmap_test_fd < 0) + throw0(DB_ERROR((std::string("Failed to check for mmap support: open failed: ") + strerror(errno)).c_str())); + epee::misc_utils::auto_scope_leave_caller scope_exit_handler = epee::misc_utils::create_scope_leave_handler([mmap_test_fd, &mmap_test_file]() { + ::close(mmap_test_fd); + boost::filesystem::remove(mmap_test_file.string()); + }); + if (write(mmap_test_fd, "mmaptest", 8) != 8) + throw0(DB_ERROR((std::string("Failed to check for mmap support: write failed: ") + strerror(errno)).c_str())); + void *mmap_res = mmap(NULL, 8, PROT_READ, MAP_SHARED, mmap_test_fd, 0); + if (mmap_res == MAP_FAILED) + throw0(DB_ERROR("This filesystem does not support mmap: use --data-dir to place the blockchain on a filesystem which does")); + munmap(mmap_res, 8); +#endif +} + void BlockchainLMDB::open(const std::string& filename, const int db_flags) { int result; @@ -1328,6 +1355,8 @@ void BlockchainLMDB::open(const std::string& filename, const int db_flags) m_folder = filename; + check_mmap_support(); + #ifdef __OpenBSD__ if ((mdb_flags & MDB_WRITEMAP) == 0) { MCLOG_RED(el::Level::Info, "global", "Running on OpenBSD: forcing WRITEMAP"); @@ -2750,6 +2779,44 @@ difficulty_type BlockchainLMDB::get_block_difficulty(const uint64_t& height) con return diff1 - diff2; } +void BlockchainLMDB::correct_block_cumulative_difficulties(const uint64_t& start_height, const std::vector<difficulty_type>& new_cumulative_difficulties) +{ + LOG_PRINT_L3("BlockchainLMDB::" << __func__); + check_open(); + mdb_txn_cursors *m_cursors = &m_wcursors; + + int result = 0; + block_wtxn_start(); + CURSOR(block_info) + + const uint64_t bc_height = height(); + if (start_height + new_cumulative_difficulties.size() != bc_height) + { + block_wtxn_abort(); + throw0(DB_ERROR("Incorrect new_cumulative_difficulties size")); + } + + for (uint64_t height = start_height; height < bc_height; ++height) + { + MDB_val_set(key, height); + result = mdb_cursor_get(m_cur_block_info, (MDB_val *)&zerokval, &key, MDB_GET_BOTH); + if (result) + throw1(BLOCK_DNE(lmdb_error("Failed to get block info: ", result).c_str())); + + mdb_block_info bi = *(mdb_block_info*)key.mv_data; + const difficulty_type d = new_cumulative_difficulties[height - start_height]; + bi.bi_diff_hi = ((d >> 64) & 0xffffffffffffffff).convert_to<uint64_t>(); + bi.bi_diff_lo = (d & 0xffffffffffffffff).convert_to<uint64_t>(); + + MDB_val_set(key2, height); + MDB_val_set(val, bi); + result = mdb_cursor_put(m_cur_block_info, &key2, &val, MDB_CURRENT); + if (result) + throw0(DB_ERROR(lmdb_error("Failed to overwrite block info to db transaction: ", result).c_str())); + } + block_wtxn_stop(); +} + uint64_t BlockchainLMDB::get_block_already_generated_coins(const uint64_t& height) const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); @@ -4048,7 +4115,7 @@ void BlockchainLMDB::get_output_tx_and_index_from_global(const std::vector<uint6 void BlockchainLMDB::get_output_key(const epee::span<const uint64_t> &amounts, const std::vector<uint64_t> &offsets, std::vector<output_data_t> &outputs, bool allow_partial) const { if (amounts.size() != 1 && amounts.size() != offsets.size()) - throw0(DB_ERROR("Invalid sizes of amounts and offets")); + throw0(DB_ERROR("Invalid sizes of amounts and offsets")); LOG_PRINT_L3("BlockchainLMDB::" << __func__); TIME_MEASURE_START(db3); diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index 6ddeed671..5abb8014f 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2014-2020, The Monero Project // All rights reserved. // // Redistribution and use in source and binary forms, with or without modification, are @@ -229,6 +229,8 @@ public: virtual difficulty_type get_block_difficulty(const uint64_t& height) const; + virtual void correct_block_cumulative_difficulties(const uint64_t& start_height, const std::vector<difficulty_type>& new_cumulative_difficulties); + virtual uint64_t get_block_already_generated_coins(const uint64_t& height) const; virtual uint64_t get_block_long_term_weight(const uint64_t& height) const; @@ -356,6 +358,7 @@ public: static int compare_string(const MDB_val *a, const MDB_val *b); private: + void check_mmap_support(); void do_resize(uint64_t size_increase=0); bool need_resize(uint64_t threshold_size=0) const; diff --git a/src/blockchain_db/locked_txn.h b/src/blockchain_db/locked_txn.h index d14631ddb..1834f56fb 100644 --- a/src/blockchain_db/locked_txn.h +++ b/src/blockchain_db/locked_txn.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2014-2020, The Monero Project // // All rights reserved. // diff --git a/src/blockchain_db/testdb.h b/src/blockchain_db/testdb.h index 638dd3b37..92911d081 100644 --- a/src/blockchain_db/testdb.h +++ b/src/blockchain_db/testdb.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2019, The Monero Project +// Copyright (c) 2014-2020, The Monero Project // // All rights reserved. // @@ -69,8 +69,8 @@ public: virtual cryptonote::blobdata get_block_blob(const crypto::hash& h) const override { return cryptonote::blobdata(); } virtual bool get_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override { return false; } virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override { return false; } - virtual bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const { return false; } - virtual bool get_blocks_from(uint64_t start_height, size_t min_count, size_t max_count, size_t max_size, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata>>>>& blocks, bool pruned, bool skip_coinbase, bool get_miner_tx_hash) const { return false; } + virtual bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const override { return false; } + virtual bool get_blocks_from(uint64_t start_height, size_t min_count, size_t max_count, size_t max_size, std::vector<std::pair<std::pair<cryptonote::blobdata, crypto::hash>, std::vector<std::pair<crypto::hash, cryptonote::blobdata>>>>& blocks, bool pruned, bool skip_coinbase, bool get_miner_tx_hash) const override { return false; } virtual bool get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const override { return false; } virtual bool get_prunable_tx_hash(const crypto::hash& tx_hash, crypto::hash &prunable_hash) const override { return false; } virtual uint64_t get_block_height(const crypto::hash& h) const override { return 0; } @@ -82,6 +82,7 @@ public: virtual std::vector<uint64_t> get_block_weights(uint64_t start_height, size_t count) const override { return {}; } virtual cryptonote::difficulty_type get_block_cumulative_difficulty(const uint64_t& height) const override { return 10; } virtual cryptonote::difficulty_type get_block_difficulty(const uint64_t& height) const override { return 0; } + virtual void correct_block_cumulative_difficulties(const uint64_t& start_height, const std::vector<difficulty_type>& new_cumulative_difficulties) override {} virtual uint64_t get_block_already_generated_coins(const uint64_t& height) const override { return 10000000000; } virtual uint64_t get_block_long_term_weight(const uint64_t& height) const override { return 128; } virtual std::vector<uint64_t> get_long_term_block_weights(uint64_t start_height, size_t count) const override { return {}; } |