diff options
Diffstat (limited to 'src/blockchain_db')
-rw-r--r-- | src/blockchain_db/blockchain_db.cpp | 6 | ||||
-rw-r--r-- | src/blockchain_db/blockchain_db.h | 18 | ||||
-rw-r--r-- | src/blockchain_db/lmdb/db_lmdb.cpp | 52 | ||||
-rw-r--r-- | src/blockchain_db/lmdb/db_lmdb.h | 1 | ||||
-rw-r--r-- | src/blockchain_db/locked_txn.h | 53 | ||||
-rw-r--r-- | src/blockchain_db/testdb.h | 1 |
6 files changed, 126 insertions, 5 deletions
diff --git a/src/blockchain_db/blockchain_db.cpp b/src/blockchain_db/blockchain_db.cpp index 5fec22d8d..1a6a19da5 100644 --- a/src/blockchain_db/blockchain_db.cpp +++ b/src/blockchain_db/blockchain_db.cpp @@ -67,7 +67,7 @@ bool matches_category(relay_method method, relay_category category) noexcept case relay_method::local: return false; case relay_method::block: - case relay_method::flood: + case relay_method::fluff: return true; case relay_method::none: break; @@ -90,7 +90,7 @@ void txpool_tx_meta_t::set_relay_method(relay_method method) noexcept is_local = 1; break; default: - case relay_method::flood: + case relay_method::fluff: break; case relay_method::block: kept_by_block = 1; @@ -106,7 +106,7 @@ relay_method txpool_tx_meta_t::get_relay_method() const noexcept return relay_method::none; if (is_local) return relay_method::local; - return relay_method::flood; + return relay_method::fluff; } const command_line::arg_descriptor<std::string> arg_db_sync_mode = { diff --git a/src/blockchain_db/blockchain_db.h b/src/blockchain_db/blockchain_db.h index b2c5d6cb4..e9fc85803 100644 --- a/src/blockchain_db/blockchain_db.h +++ b/src/blockchain_db/blockchain_db.h @@ -108,7 +108,7 @@ extern const command_line::arg_descriptor<bool, false> arg_db_salvage; enum class relay_category : uint8_t { - broadcasted = 0,//!< Public txes received via block/flooding/fluff + broadcasted = 0,//!< Public txes received via block/fluff relayable, //!< Every tx not marked `relay_method::none` legacy, //!< `relay_category::broadcasted` + `relay_method::none` for rpc relay requests or historical reasons all //!< Everything in the db @@ -1275,6 +1275,22 @@ public: virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const = 0; /** + * @brief fetches a number of pruned transaction blob from the given hash, in canonical blockchain order + * + * The subclass should return the pruned transactions stored from the one with the given + * hash. + * + * If the first transaction does not exist, the subclass should return false. + * If the first transaction exists, but there are fewer transactions starting with it + * than requested, the subclass should return false. + * + * @param h the hash to look for + * + * @return true iff the transactions were found + */ + virtual bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const = 0; + + /** * @brief fetches the prunable transaction blob with the given hash * * The subclass should return the prunable transaction stored which has the given diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index e8667adcf..5093015f2 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -163,7 +163,15 @@ int BlockchainLMDB::compare_string(const MDB_val *a, const MDB_val *b) { const char *va = (const char*) a->mv_data; const char *vb = (const char*) b->mv_data; - return strcmp(va, vb); + const size_t sz = std::min(a->mv_size, b->mv_size); + int ret = strncmp(va, vb, sz); + if (ret) + return ret; + if (a->mv_size < b->mv_size) + return -1; + if (a->mv_size > b->mv_size) + return 1; + return 0; } } @@ -3057,6 +3065,48 @@ bool BlockchainLMDB::get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobd return true; } +bool BlockchainLMDB::get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const +{ + LOG_PRINT_L3("BlockchainLMDB::" << __func__); + check_open(); + + if (!count) + return true; + + TXN_PREFIX_RDONLY(); + RCURSOR(tx_indices); + RCURSOR(txs_pruned); + + bd.reserve(bd.size() + count); + + MDB_val_set(v, h); + MDB_val result; + int res = mdb_cursor_get(m_cur_tx_indices, (MDB_val *)&zerokval, &v, MDB_GET_BOTH); + if (res == MDB_NOTFOUND) + return false; + if (res) + throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx from hash", res).c_str())); + + const txindex *tip = (const txindex *)v.mv_data; + const uint64_t id = tip->data.tx_id; + MDB_val_set(val_tx_id, id); + MDB_cursor_op op = MDB_SET; + while (count--) + { + res = mdb_cursor_get(m_cur_txs_pruned, &val_tx_id, &result, op); + op = MDB_NEXT; + if (res == MDB_NOTFOUND) + return false; + if (res) + throw0(DB_ERROR(lmdb_error("DB error attempting to fetch tx blob", res).c_str())); + bd.emplace_back(reinterpret_cast<char*>(result.mv_data), result.mv_size); + } + + TXN_POSTFIX_RDONLY(); + + return true; +} + bool BlockchainLMDB::get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &bd) const { LOG_PRINT_L3("BlockchainLMDB::" << __func__); diff --git a/src/blockchain_db/lmdb/db_lmdb.h b/src/blockchain_db/lmdb/db_lmdb.h index e56711e8f..7c0b4c72c 100644 --- a/src/blockchain_db/lmdb/db_lmdb.h +++ b/src/blockchain_db/lmdb/db_lmdb.h @@ -254,6 +254,7 @@ public: virtual bool get_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const; virtual bool get_pruned_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const; + virtual bool get_pruned_tx_blobs_from(const crypto::hash& h, size_t count, std::vector<cryptonote::blobdata> &bd) const; virtual bool get_prunable_tx_blob(const crypto::hash& h, cryptonote::blobdata &tx) const; virtual bool get_prunable_tx_hash(const crypto::hash& tx_hash, crypto::hash &prunable_hash) const; diff --git a/src/blockchain_db/locked_txn.h b/src/blockchain_db/locked_txn.h new file mode 100644 index 000000000..d14631ddb --- /dev/null +++ b/src/blockchain_db/locked_txn.h @@ -0,0 +1,53 @@ +// Copyright (c) 2014-2019, The Monero Project +// +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without modification, are +// permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, this list of +// conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright notice, this list +// of conditions and the following disclaimer in the documentation and/or other +// materials provided with the distribution. +// +// 3. Neither the name of the copyright holder nor the names of its contributors may be +// used to endorse or promote products derived from this software without specific +// prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL +// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +// 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. +// +// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers + +#pragma once + +namespace cryptonote +{ + // This class is meant to create a batch when none currently exists. + // If a batch exists, it can't be from another thread, since we can + // only be called with the txpool lock taken, and it is held during + // the whole prepare/handle/cleanup incoming block sequence. + class LockedTXN { + public: + LockedTXN(BlockchainDB &db): m_db(db), m_batch(false), m_active(false) { + m_batch = m_db.batch_start(); + m_active = true; + } + void commit() { try { if (m_batch && m_active) { m_db.batch_stop(); m_active = false; } } catch (const std::exception &e) { MWARNING("LockedTXN::commit filtering exception: " << e.what()); } } + void abort() { try { if (m_batch && m_active) { m_db.batch_abort(); m_active = false; } } catch (const std::exception &e) { MWARNING("LockedTXN::abort filtering exception: " << e.what()); } } + ~LockedTXN() { abort(); } + private: + BlockchainDB &m_db; + bool m_batch; + bool m_active; + }; +} diff --git a/src/blockchain_db/testdb.h b/src/blockchain_db/testdb.h index a5847dec6..46de38c7e 100644 --- a/src/blockchain_db/testdb.h +++ b/src/blockchain_db/testdb.h @@ -69,6 +69,7 @@ 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_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; } |