aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--README.md10
-rw-r--r--contrib/gitian/README.md4
-rw-r--r--src/blocks/checkpoints.datbin277956 -> 279428 bytes
-rw-r--r--src/checkpoints/checkpoints.cpp1
-rw-r--r--src/cryptonote_config.h4
-rw-r--r--src/cryptonote_core/blockchain.cpp2
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp7
-rw-r--r--src/cryptonote_core/cryptonote_core.h12
-rw-r--r--src/cryptonote_core/i_core_events.h3
-rw-r--r--src/cryptonote_core/tx_pool.cpp45
-rw-r--r--src/cryptonote_core/tx_pool.h11
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.h2
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler.inl6
-rw-r--r--src/cryptonote_protocol/cryptonote_protocol_handler_common.h5
-rw-r--r--src/cryptonote_protocol/levin_notify.cpp58
-rw-r--r--src/rpc/bootstrap_daemon.cpp10
-rw-r--r--src/rpc/bootstrap_daemon.h3
-rw-r--r--src/rpc/core_rpc_server.cpp29
-rw-r--r--src/version.cpp.in2
-rw-r--r--tests/core_proxy/core_proxy.h3
-rw-r--r--tests/unit_tests/levin.cpp7
-rw-r--r--tests/unit_tests/node_server.cpp3
22 files changed, 170 insertions, 57 deletions
diff --git a/README.md b/README.md
index 11c0fb0ba..bfc70a544 100644
--- a/README.md
+++ b/README.md
@@ -134,8 +134,8 @@ Dates are provided in the format YYYY-MM-DD.
| 1788000 | 2019-03-09 | v10 | v0.14.0.0 | v0.14.1.2 | New PoW based on Cryptonight-R, new block weight algorithm, slightly more efficient RingCT format
| 1788720 | 2019-03-10 | v11 | v0.14.0.0 | v0.14.1.2 | forbid old RingCT transaction format
| 1978433 | 2019-11-30* | v12 | v0.15.0.0 | v0.16.0.0 | New PoW based on RandomX, only allow >= 2 outputs, change to the block median used to calculate penalty, v1 coinbases are forbidden, rct sigs in coinbase forbidden, 10 block lock time for incoming outputs
-| 2210000 | 2020-10-17 | v13 | v0.17.0.0 | v0.17.1.3 | New CLSAG transaction format
-| 2210720 | 2020-10-18 | v14 | v0.17.1.1 | v0.17.1.3 | forbid old MLSAG transaction format
+| 2210000 | 2020-10-17 | v13 | v0.17.0.0 | v0.17.1.5 | New CLSAG transaction format
+| 2210720 | 2020-10-18 | v14 | v0.17.1.1 | v0.17.1.5 | forbid old MLSAG transaction format
| XXXXXXX | XXX-XX-XX | XXX | vX.XX.X.X | vX.XX.X.X | XXX |
X's indicate that these details have not been determined as of commit date.
@@ -295,7 +295,7 @@ Tested on a Raspberry Pi Zero with a clean install of minimal Raspbian Stretch (
```bash
git clone https://github.com/monero-project/monero.git
cd monero
- git checkout tags/v0.17.1.3
+ git checkout tags/v0.17.1.5
```
* Build:
@@ -412,10 +412,10 @@ application.
cd monero
```
-* If you would like a specific [version/tag](https://github.com/monero-project/monero/tags), do a git checkout for that version. eg. 'v0.17.1.3'. If you don't care about the version and just want binaries from master, skip this step:
+* If you would like a specific [version/tag](https://github.com/monero-project/monero/tags), do a git checkout for that version. eg. 'v0.17.1.5'. If you don't care about the version and just want binaries from master, skip this step:
```bash
- git checkout v0.17.1.3
+ git checkout v0.17.1.5
```
* If you are on a 64-bit system, run:
diff --git a/contrib/gitian/README.md b/contrib/gitian/README.md
index 9ca369e49..12a9b3e68 100644
--- a/contrib/gitian/README.md
+++ b/contrib/gitian/README.md
@@ -126,7 +126,7 @@ Setup for LXC:
```bash
GH_USER=fluffypony
-VERSION=v0.17.1.3
+VERSION=v0.17.1.5
./gitian-build.py --setup $GH_USER $VERSION
```
@@ -182,7 +182,7 @@ If you chose to do detached signing using `--detach-sign` above (recommended), y
```bash
GH_USER=fluffypony
-VERSION=v0.17.1.3
+VERSION=v0.17.1.5
gpg --detach-sign ${VERSION}-linux/${GH_USER}/monero-linux-*-build.assert
gpg --detach-sign ${VERSION}-win/${GH_USER}/monero-win-*-build.assert
diff --git a/src/blocks/checkpoints.dat b/src/blocks/checkpoints.dat
index 1332ec5f7..bcbfbb7ee 100644
--- a/src/blocks/checkpoints.dat
+++ b/src/blocks/checkpoints.dat
Binary files differ
diff --git a/src/checkpoints/checkpoints.cpp b/src/checkpoints/checkpoints.cpp
index 93bbeee46..d966eebda 100644
--- a/src/checkpoints/checkpoints.cpp
+++ b/src/checkpoints/checkpoints.cpp
@@ -241,6 +241,7 @@ namespace cryptonote
ADD_CHECKPOINT2(2206500, "dd3c8590f33eaa546a4ce69d02f27fd58a2f115cd32d733bd9426f8278f0cb8a", "0xf8725275799f0d");
ADD_CHECKPOINT2(2210500, "ed17259215ac6aabe6e8252b5b5eff613d2e69cc2111173e567109aa78301911", "0xfbcb50a9a6a433");
ADD_CHECKPOINT2(2224000, "e34bc71301600df96d08aaa6b0bde932cba1b06a3dd57076e3f664a078810a80", "0x1052fc256fceb6f");
+ ADD_CHECKPOINT2(2235500, "3eac1a1253495733e10d00fd5e8e1639741566d91bae38bc6d3342af6b75da53", "0x10cea232ce71d23");
return true;
}
diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h
index bc17b7e81..826cabe17 100644
--- a/src/cryptonote_config.h
+++ b/src/cryptonote_config.h
@@ -102,11 +102,11 @@
#define CRYPTONOTE_DANDELIONPP_STEMS 2 // number of outgoing stem connections per epoch
-#define CRYPTONOTE_DANDELIONPP_FLUFF_PROBABILITY 10 // out of 100
+#define CRYPTONOTE_DANDELIONPP_FLUFF_PROBABILITY 20 // out of 100
#define CRYPTONOTE_DANDELIONPP_MIN_EPOCH 10 // minutes
#define CRYPTONOTE_DANDELIONPP_EPOCH_RANGE 30 // seconds
#define CRYPTONOTE_DANDELIONPP_FLUSH_AVERAGE 5 // seconds average for poisson distributed fluff flush
-#define CRYPTONOTE_DANDELIONPP_EMBARGO_AVERAGE 173 // seconds (see tx_pool.cpp for more info)
+#define CRYPTONOTE_DANDELIONPP_EMBARGO_AVERAGE 39 // seconds (see tx_pool.cpp for more info)
// see src/cryptonote_protocol/levin_notify.cpp
#define CRYPTONOTE_NOISE_MIN_EPOCH 5 // minutes
diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp
index d4b844c58..89ecda2cd 100644
--- a/src/cryptonote_core/blockchain.cpp
+++ b/src/cryptonote_core/blockchain.cpp
@@ -5376,7 +5376,7 @@ void Blockchain::cancel()
}
#if defined(PER_BLOCK_CHECKPOINT)
-static const char expected_block_hashes_hash[] = "1d166275537bfbb5841d98da298c65089f3006d751776b2dc8a4f0275ef0ce58";
+static const char expected_block_hashes_hash[] = "3a2a0720f7ed3573d2b632f7ba127e2f97edac3af34bf924df57c13a88bf2460";
void Blockchain::load_compiled_in_block_hashes(const GetCheckpointsCallback& get_checkpoints)
{
if (get_checkpoints == nullptr || !m_fast_sync)
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index fef411a0c..42b1c6c84 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -1510,6 +1510,11 @@ namespace cryptonote
return true;
}
//-----------------------------------------------------------------------------------------------
+ bool core::is_synchronized() const
+ {
+ return m_pprotocol != nullptr && m_pprotocol->is_synchronized();
+ }
+ //-----------------------------------------------------------------------------------------------
void core::on_synchronized()
{
m_miner.on_synchronized();
@@ -1725,7 +1730,7 @@ namespace cryptonote
m_starter_message_showed = true;
}
- m_txpool_auto_relayer.do_call(boost::bind(&core::relay_txpool_transactions, this));
+ relay_txpool_transactions(); // txpool handles periodic DB checking
m_check_updates_interval.do_call(boost::bind(&core::check_updates, this));
m_check_disk_space_interval.do_call(boost::bind(&core::check_disk_space, this));
m_block_rate_interval.do_call(boost::bind(&core::check_block_rate, this));
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index 7c578ac51..da7a21b27 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -329,7 +329,7 @@ namespace cryptonote
*
* @note see Blockchain::get_current_blockchain_height()
*/
- uint64_t get_current_blockchain_height() const;
+ virtual uint64_t get_current_blockchain_height() const final;
/**
* @brief get the hash and height of the most recent block
@@ -638,6 +638,13 @@ namespace cryptonote
std::string print_pool(bool short_format) const;
/**
+ * @brief gets the core synchronization status
+ *
+ * @return core synchronization status
+ */
+ virtual bool is_synchronized() const final;
+
+ /**
* @copydoc miner::on_synchronized
*
* @note see miner::on_synchronized
@@ -663,7 +670,7 @@ namespace cryptonote
*
* @param target_blockchain_height the target height
*/
- virtual uint64_t get_target_blockchain_height() const override;
+ uint64_t get_target_blockchain_height() const;
/**
* @brief returns the newest hardfork version known to the blockchain
@@ -1065,7 +1072,6 @@ namespace cryptonote
epee::math_helper::once_a_time_seconds<60*60*12, false> m_store_blockchain_interval; //!< interval for manual storing of Blockchain, if enabled
epee::math_helper::once_a_time_seconds<60*60*2, true> m_fork_moaner; //!< interval for checking HardFork status
- epee::math_helper::once_a_time_seconds<60*2, false> m_txpool_auto_relayer; //!< interval for checking re-relaying txpool transactions
epee::math_helper::once_a_time_seconds<60*60*12, true> m_check_updates_interval; //!< interval for checking for new versions
epee::math_helper::once_a_time_seconds<60*10, true> m_check_disk_space_interval; //!< interval for checking for disk space
epee::math_helper::once_a_time_seconds<90, false> m_block_rate_interval; //!< interval for checking block rate
diff --git a/src/cryptonote_core/i_core_events.h b/src/cryptonote_core/i_core_events.h
index addb659ab..5d00858b5 100644
--- a/src/cryptonote_core/i_core_events.h
+++ b/src/cryptonote_core/i_core_events.h
@@ -39,7 +39,8 @@ namespace cryptonote
virtual ~i_core_events() noexcept
{}
- virtual uint64_t get_target_blockchain_height() const = 0;
+ virtual uint64_t get_current_blockchain_height() const = 0;
+ virtual bool is_synchronized() const = 0;
virtual void on_transactions_relayed(epee::span<const cryptonote::blobdata> tx_blobs, relay_method tx_relay) = 0;
};
}
diff --git a/src/cryptonote_core/tx_pool.cpp b/src/cryptonote_core/tx_pool.cpp
index 28721ee36..d059ab78f 100644
--- a/src/cryptonote_core/tx_pool.cpp
+++ b/src/cryptonote_core/tx_pool.cpp
@@ -75,11 +75,11 @@ namespace cryptonote
not ideal since a blackhole is more likely to reveal earlier nodes in
the chain.
- This value was calculated with k=10, ep=0.10, and hop = 175 ms. A
+ This value was calculated with k=5, ep=0.10, and hop = 175 ms. A
testrun from a recent Intel laptop took ~80ms to
receive+parse+proces+send transaction. At least 50ms will be added to
the latency if crossing an ocean. So 175ms is the fudge factor for
- a single hop with 173s being the embargo timer. */
+ a single hop with 39s being the embargo timer. */
constexpr const std::chrono::seconds dandelionpp_embargo_average{CRYPTONOTE_DANDELIONPP_EMBARGO_AVERAGE};
//TODO: constants such as these should at least be in the header,
@@ -91,6 +91,9 @@ namespace cryptonote
time_t const MAX_RELAY_TIME = (60 * 60 * 4); // at most that many seconds between resends
float const ACCEPT_THRESHOLD = 1.0f;
+ //! Max DB check interval for relayable txes
+ constexpr const std::chrono::minutes max_relayable_check{2};
+
constexpr const std::chrono::seconds forward_delay_average{CRYPTONOTE_FORWARD_DELAY_AVERAGE};
// a kind of increasing backoff within min/max bounds
@@ -115,12 +118,21 @@ namespace cryptonote
else
return get_min_block_weight(version) - CRYPTONOTE_COINBASE_BLOB_RESERVED_SIZE;
}
+
+ // external lock must be held for the comparison+set to work properly
+ void set_if_less(std::atomic<time_t>& next_check, const time_t candidate) noexcept
+ {
+ if (candidate < next_check.load(std::memory_order_relaxed))
+ next_check = candidate;
+ }
}
//---------------------------------------------------------------------------------
//---------------------------------------------------------------------------------
- tx_memory_pool::tx_memory_pool(Blockchain& bchs): m_blockchain(bchs), m_cookie(0), m_txpool_max_weight(DEFAULT_TXPOOL_MAX_WEIGHT), m_txpool_weight(0), m_mine_stem_txes(false)
+ tx_memory_pool::tx_memory_pool(Blockchain& bchs): m_blockchain(bchs), m_cookie(0), m_txpool_max_weight(DEFAULT_TXPOOL_MAX_WEIGHT), m_txpool_weight(0), m_mine_stem_txes(false), m_next_check(std::time(nullptr))
{
-
+ // class code expects unsigned values throughout
+ if (m_next_check < time_t(0))
+ throw std::runtime_error{"Unexpected time_t (system clock) value"};
}
//---------------------------------------------------------------------------------
bool tx_memory_pool::add_tx(transaction &tx, /*const crypto::hash& tx_prefix_hash,*/ const crypto::hash &id, const cryptonote::blobdata &blob, size_t tx_weight, tx_verification_context& tvc, relay_method tx_relay, bool relayed, uint8_t version)
@@ -314,7 +326,10 @@ namespace cryptonote
using clock = std::chrono::system_clock;
auto last_relayed_time = std::numeric_limits<decltype(meta.last_relayed_time)>::max();
if (tx_relay == relay_method::forward)
+ {
last_relayed_time = clock::to_time_t(clock::now() + crypto::random_poisson_seconds{forward_delay_average}());
+ set_if_less(m_next_check, time_t(last_relayed_time));
+ }
// else the `set_relayed` function will adjust the time accordingly later
//update transactions container
@@ -728,16 +743,22 @@ namespace cryptonote
}
//---------------------------------------------------------------------------------
//TODO: investigate whether boolean return is appropriate
- bool tx_memory_pool::get_relayable_transactions(std::vector<std::tuple<crypto::hash, cryptonote::blobdata, relay_method>> &txs) const
+ bool tx_memory_pool::get_relayable_transactions(std::vector<std::tuple<crypto::hash, cryptonote::blobdata, relay_method>> &txs)
{
- std::vector<std::pair<crypto::hash, txpool_tx_meta_t>> change_timestamps;
+ using clock = std::chrono::system_clock;
+
const uint64_t now = time(NULL);
+ if (uint64_t{std::numeric_limits<time_t>::max()} < now || time_t(now) < m_next_check)
+ return false;
+
+ uint64_t next_check = clock::to_time_t(clock::from_time_t(time_t(now)) + max_relayable_check);
+ std::vector<std::pair<crypto::hash, txpool_tx_meta_t>> change_timestamps;
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
LockedTXN lock(m_blockchain.get_db());
txs.reserve(m_blockchain.get_txpool_tx_count());
- m_blockchain.for_all_txpool_txes([this, now, &txs, &change_timestamps](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *){
+ m_blockchain.for_all_txpool_txes([this, now, &txs, &change_timestamps, &next_check](const crypto::hash &txid, const txpool_tx_meta_t &meta, const cryptonote::blobdata_ref *){
// 0 fee transactions are never relayed
if(!meta.pruned && meta.fee > 0 && !meta.do_not_relay)
{
@@ -747,7 +768,10 @@ namespace cryptonote
case relay_method::stem:
case relay_method::forward:
if (meta.last_relayed_time > now)
+ {
+ next_check = std::min(next_check, meta.last_relayed_time);
return true; // continue to next tx
+ }
change_timestamps.emplace_back(txid, meta);
break;
default:
@@ -792,6 +816,8 @@ namespace cryptonote
elem.second.last_relayed_time = now + get_relay_delay(now, elem.second.receive_time);
m_blockchain.update_txpool_tx(elem.first, elem.second);
}
+
+ m_next_check = time_t(next_check);
return true;
}
//---------------------------------------------------------------------------------
@@ -799,6 +825,7 @@ namespace cryptonote
{
crypto::random_poisson_seconds embargo_duration{dandelionpp_embargo_average};
const auto now = std::chrono::system_clock::now();
+ uint64_t next_relay = uint64_t{std::numeric_limits<time_t>::max()};
CRITICAL_REGION_LOCAL(m_transactions_lock);
CRITICAL_REGION_LOCAL1(m_blockchain);
@@ -815,7 +842,10 @@ namespace cryptonote
meta.relayed = true;
if (meta.dandelionpp_stem)
+ {
meta.last_relayed_time = std::chrono::system_clock::to_time_t(now + embargo_duration());
+ next_relay = std::min(next_relay, meta.last_relayed_time);
+ }
else
meta.last_relayed_time = std::chrono::system_clock::to_time_t(now);
@@ -829,6 +859,7 @@ namespace cryptonote
}
}
lock.commit();
+ set_if_less(m_next_check, time_t(next_relay));
}
//---------------------------------------------------------------------------------
size_t tx_memory_pool::get_transactions_count(bool include_sensitive) const
diff --git a/src/cryptonote_core/tx_pool.h b/src/cryptonote_core/tx_pool.h
index 8955d7551..ab2a57ea2 100644
--- a/src/cryptonote_core/tx_pool.h
+++ b/src/cryptonote_core/tx_pool.h
@@ -31,6 +31,7 @@
#pragma once
#include "include_base_utils.h"
+#include <atomic>
#include <set>
#include <tuple>
#include <unordered_map>
@@ -329,11 +330,14 @@ namespace cryptonote
* isn't old enough that relaying it is considered harmful
* Note a transaction can be "relayable" even if do_not_relay is true
*
+ * This function will skip all DB checks if an insufficient amount of
+ * time since the last call.
+ *
* @param txs return-by-reference the transactions and their hashes
*
- * @return true
+ * @return True if DB was checked, false if DB checks skipped.
*/
- bool get_relayable_transactions(std::vector<std::tuple<crypto::hash, cryptonote::blobdata, relay_method>>& txs) const;
+ bool get_relayable_transactions(std::vector<std::tuple<crypto::hash, cryptonote::blobdata, relay_method>>& txs);
/**
* @brief tell the pool that certain transactions were just relayed
@@ -609,6 +613,9 @@ private:
mutable std::unordered_map<crypto::hash, std::tuple<bool, tx_verification_context, uint64_t, crypto::hash>> m_input_cache;
std::unordered_map<crypto::hash, transaction> m_parsed_tx_cache;
+
+ //! Next timestamp that a DB check for relayable txes is allowed
+ std::atomic<time_t> m_next_check;
};
}
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.h b/src/cryptonote_protocol/cryptonote_protocol_handler.h
index 89860fe41..61aac6d81 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.h
@@ -104,7 +104,7 @@ namespace cryptonote
bool get_payload_sync_data(CORE_SYNC_DATA& hshd);
bool on_callback(cryptonote_connection_context& context);
t_core& get_core(){return m_core;}
- bool is_synchronized(){return m_synchronized;}
+ virtual bool is_synchronized() const final { return !no_sync() && m_synchronized; }
void log_connections();
std::list<connection_info> get_connections();
const block_queue &get_block_queue() const { return m_block_queue; }
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler.inl b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
index 20bcd7f3b..a72b7db79 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler.inl
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler.inl
@@ -430,7 +430,7 @@ namespace cryptonote
MLOGIF_P2P_MESSAGE(crypto::hash hash; cryptonote::block b; bool ret = cryptonote::parse_and_validate_block_from_blob(arg.b.block, b, &hash);, ret, "Received NOTIFY_NEW_BLOCK " << hash << " (height " << arg.current_blockchain_height << ", " << arg.b.txs.size() << " txes)");
if(context.m_state != cryptonote_connection_context::state_normal)
return 1;
- if(!is_synchronized() || m_no_sync) // can happen if a peer connection goes to normal but another thread still hasn't finished adding queued blocks
+ if(!is_synchronized()) // can happen if a peer connection goes to normal but another thread still hasn't finished adding queued blocks
{
LOG_DEBUG_CC(context, "Received new block while syncing, ignored");
return 1;
@@ -501,7 +501,7 @@ namespace cryptonote
MLOGIF_P2P_MESSAGE(crypto::hash hash; cryptonote::block b; bool ret = cryptonote::parse_and_validate_block_from_blob(arg.b.block, b, &hash);, ret, "Received NOTIFY_NEW_FLUFFY_BLOCK " << hash << " (height " << arg.current_blockchain_height << ", " << arg.b.txs.size() << " txes)");
if(context.m_state != cryptonote_connection_context::state_normal)
return 1;
- if(!is_synchronized() || m_no_sync) // can happen if a peer connection goes to normal but another thread still hasn't finished adding queued blocks
+ if(!is_synchronized()) // can happen if a peer connection goes to normal but another thread still hasn't finished adding queued blocks
{
LOG_DEBUG_CC(context, "Received new block while syncing, ignored");
return 1;
@@ -929,7 +929,7 @@ namespace cryptonote
// while syncing, core will lock for a long time, so we ignore
// those txes as they aren't really needed anyway, and avoid a
// long block before replying
- if(!is_synchronized() || m_no_sync)
+ if(!is_synchronized())
{
LOG_DEBUG_CC(context, "Received new tx while syncing, ignored");
return 1;
diff --git a/src/cryptonote_protocol/cryptonote_protocol_handler_common.h b/src/cryptonote_protocol/cryptonote_protocol_handler_common.h
index 1c7635fd8..79c2edf1d 100644
--- a/src/cryptonote_protocol/cryptonote_protocol_handler_common.h
+++ b/src/cryptonote_protocol/cryptonote_protocol_handler_common.h
@@ -40,6 +40,7 @@ namespace cryptonote
/************************************************************************/
struct i_cryptonote_protocol
{
+ virtual bool is_synchronized() const = 0;
virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& exclude_context)=0;
virtual bool relay_transactions(NOTIFY_NEW_TRANSACTIONS::request& arg, const boost::uuids::uuid& source, epee::net_utils::zone zone, relay_method tx_relay)=0;
//virtual bool request_objects(NOTIFY_REQUEST_GET_OBJECTS::request& arg, cryptonote_connection_context& context)=0;
@@ -50,6 +51,10 @@ namespace cryptonote
/************************************************************************/
struct cryptonote_protocol_stub: public i_cryptonote_protocol
{
+ virtual bool is_synchronized() const final
+ {
+ return false;
+ }
virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& exclude_context)
{
return false;
diff --git a/src/cryptonote_protocol/levin_notify.cpp b/src/cryptonote_protocol/levin_notify.cpp
index bbec2ba9b..69df22a92 100644
--- a/src/cryptonote_protocol/levin_notify.cpp
+++ b/src/cryptonote_protocol/levin_notify.cpp
@@ -105,8 +105,44 @@ namespace levin
return std::chrono::steady_clock::duration{crypto::rand_range(rep(0), range.count())};
}
- //! \return Outgoing connections supporting fragments in `connections` filtered by remote blockchain height.
- std::vector<boost::uuids::uuid> get_out_connections(connections& p2p, uint64_t min_blockchain_height)
+ uint64_t get_median_remote_height(connections& p2p)
+ {
+ std::vector<uint64_t> remote_heights;
+ remote_heights.reserve(connection_id_reserve_size);
+ p2p.foreach_connection([&remote_heights] (detail::p2p_context& context) {
+ if (!context.m_is_income)
+ {
+ remote_heights.emplace_back(context.m_remote_blockchain_height);
+ }
+ return true;
+ });
+
+ if (remote_heights.empty())
+ {
+ return 0;
+ }
+
+ const size_t n = remote_heights.size() / 2;
+ std::sort(remote_heights.begin(), remote_heights.end());
+ if (remote_heights.size() % 2 != 0)
+ {
+ return remote_heights[n];
+ }
+ return remote_heights[n-1];
+ }
+
+ uint64_t get_blockchain_height(connections& p2p, const i_core_events* core)
+ {
+ const uint64_t local_blockchain_height = core->get_current_blockchain_height();
+ if (core->is_synchronized())
+ {
+ return local_blockchain_height;
+ }
+ return std::max(local_blockchain_height, get_median_remote_height(p2p));
+ }
+
+ //! \return Outgoing connections supporting fragments in `connections` filtered by blockchain height.
+ std::vector<boost::uuids::uuid> get_out_connections(connections& p2p, uint64_t blockchain_height)
{
std::vector<boost::uuids::uuid> outs;
outs.reserve(connection_id_reserve_size);
@@ -115,15 +151,21 @@ namespace levin
the reserve call so a strand is not used. Investigate if there is lots
of waiting in here. */
- p2p.foreach_connection([&outs, min_blockchain_height] (detail::p2p_context& context) {
- if (!context.m_is_income && context.m_remote_blockchain_height >= min_blockchain_height)
+ p2p.foreach_connection([&outs, blockchain_height] (detail::p2p_context& context) {
+ if (!context.m_is_income && context.m_remote_blockchain_height >= blockchain_height)
outs.emplace_back(context.m_connection_id);
return true;
});
+ MDEBUG("Found " << outs.size() << " out connections having height >= " << blockchain_height);
return outs;
}
+ std::vector<boost::uuids::uuid> get_out_connections(connections& p2p, const i_core_events* core)
+ {
+ return get_out_connections(p2p, get_blockchain_height(p2p, core));
+ }
+
std::string make_tx_payload(std::vector<blobdata>&& txs, const bool pad, const bool fluff)
{
NOTIFY_NEW_TRANSACTIONS::request request{};
@@ -527,7 +569,7 @@ namespace levin
}
// connection list may be outdated, try again
- update_channels::run(zone_, get_out_connections(*zone_->p2p, core_->get_target_blockchain_height()));
+ update_channels::run(zone_, get_out_connections(*zone_->p2p, core_));
}
MERROR("Unable to send transaction(s) via Dandelion++ stem");
@@ -631,7 +673,7 @@ namespace levin
{
channel.active = nullptr;
channel.connection = boost::uuids::nil_uuid();
- auto height = core_->get_target_blockchain_height();
+ auto height = get_blockchain_height(*zone_->p2p, core_);
auto connections = get_out_connections(*zone_->p2p, height);
if (connections.empty())
@@ -667,7 +709,7 @@ namespace levin
const bool fluffing = crypto::rand_idx(unsigned(100)) < CRYPTONOTE_DANDELIONPP_FLUFF_PROBABILITY;
const auto start = std::chrono::steady_clock::now();
- auto connections = get_out_connections(*(zone_->p2p), core_->get_target_blockchain_height());
+ auto connections = get_out_connections(*(zone_->p2p), core_);
zone_->strand.dispatch(
change_channels{zone_, net::dandelionpp::connection_map{std::move(connections), count_}, fluffing}
);
@@ -718,7 +760,7 @@ namespace levin
return;
zone_->strand.dispatch(
- update_channels{zone_, get_out_connections(*(zone_->p2p), core_->get_target_blockchain_height())}
+ update_channels{zone_, get_out_connections(*(zone_->p2p), core_)}
);
}
diff --git a/src/rpc/bootstrap_daemon.cpp b/src/rpc/bootstrap_daemon.cpp
index 6a0833f19..2fdd28406 100644
--- a/src/rpc/bootstrap_daemon.cpp
+++ b/src/rpc/bootstrap_daemon.cpp
@@ -45,12 +45,12 @@ namespace cryptonote
return host + ":" + m_http_client.get_port();
}
- boost::optional<uint64_t> bootstrap_daemon::get_height()
+ boost::optional<std::pair<uint64_t, uint64_t>> bootstrap_daemon::get_height()
{
- cryptonote::COMMAND_RPC_GET_HEIGHT::request req;
- cryptonote::COMMAND_RPC_GET_HEIGHT::response res;
+ cryptonote::COMMAND_RPC_GET_INFO::request req;
+ cryptonote::COMMAND_RPC_GET_INFO::response res;
- if (!invoke_http_json("/getheight", req, res))
+ if (!invoke_http_json("/getinfo", req, res))
{
return boost::none;
}
@@ -60,7 +60,7 @@ namespace cryptonote
return boost::none;
}
- return res.height;
+ return {{res.height, res.target_height}};
}
bool bootstrap_daemon::handle_result(bool success, const std::string &status)
diff --git a/src/rpc/bootstrap_daemon.h b/src/rpc/bootstrap_daemon.h
index bedc255b5..d54042b11 100644
--- a/src/rpc/bootstrap_daemon.h
+++ b/src/rpc/bootstrap_daemon.h
@@ -2,6 +2,7 @@
#include <functional>
#include <map>
+#include <utility>
#include <boost/optional/optional.hpp>
#include <boost/thread/mutex.hpp>
@@ -27,7 +28,7 @@ namespace cryptonote
bool rpc_payment_enabled);
std::string address() const noexcept;
- boost::optional<uint64_t> get_height();
+ boost::optional<std::pair<uint64_t, uint64_t>> get_height();
bool handle_result(bool success, const std::string &status);
template <class t_request, class t_response>
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index 9b08971cd..176e080ad 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -1151,6 +1151,10 @@ namespace cryptonote
CHECK_CORE_READY();
}
}
+ else
+ {
+ CHECK_CORE_READY();
+ }
CHECK_PAYMENT_MIN1(req, res, COST_PER_TX_RELAY, false);
@@ -1987,34 +1991,37 @@ namespace cryptonote
}
auto current_time = std::chrono::system_clock::now();
- if (!m_p2p.get_payload_object().no_sync() &&
- current_time - m_bootstrap_height_check_time > std::chrono::seconds(30)) // update every 30s
+ if (current_time - m_bootstrap_height_check_time > std::chrono::seconds(30)) // update every 30s
{
{
boost::upgrade_to_unique_lock<boost::shared_mutex> lock(upgrade_lock);
m_bootstrap_height_check_time = current_time;
}
- boost::optional<uint64_t> bootstrap_daemon_height = m_bootstrap_daemon->get_height();
- if (!bootstrap_daemon_height)
+ boost::optional<std::pair<uint64_t, uint64_t>> bootstrap_daemon_height_info = m_bootstrap_daemon->get_height();
+ if (!bootstrap_daemon_height_info)
{
MERROR("Failed to fetch bootstrap daemon height");
return false;
}
- uint64_t target_height = m_core.get_target_blockchain_height();
- if (*bootstrap_daemon_height < target_height)
+ const uint64_t bootstrap_daemon_height = bootstrap_daemon_height_info->first;
+ const uint64_t bootstrap_daemon_target_height = bootstrap_daemon_height_info->second;
+ if (bootstrap_daemon_height < bootstrap_daemon_target_height)
{
MINFO("Bootstrap daemon is out of sync");
return m_bootstrap_daemon->handle_result(false, {});
}
- uint64_t top_height = m_core.get_current_blockchain_height();
- m_should_use_bootstrap_daemon = top_height + 10 < *bootstrap_daemon_height;
- MINFO((m_should_use_bootstrap_daemon ? "Using" : "Not using") << " the bootstrap daemon (our height: " << top_height << ", bootstrap daemon's height: " << *bootstrap_daemon_height << ")");
+ if (!m_p2p.get_payload_object().no_sync())
+ {
+ uint64_t top_height = m_core.get_current_blockchain_height();
+ m_should_use_bootstrap_daemon = top_height + 10 < bootstrap_daemon_height;
+ MINFO((m_should_use_bootstrap_daemon ? "Using" : "Not using") << " the bootstrap daemon (our height: " << top_height << ", bootstrap daemon's height: " << bootstrap_daemon_height << ")");
- if (!m_should_use_bootstrap_daemon)
- return false;
+ if (!m_should_use_bootstrap_daemon)
+ return false;
+ }
}
if (mode == invoke_http_mode::JON)
diff --git a/src/version.cpp.in b/src/version.cpp.in
index aa6d50926..6658cb3b1 100644
--- a/src/version.cpp.in
+++ b/src/version.cpp.in
@@ -1,5 +1,5 @@
#define DEF_MONERO_VERSION_TAG "@VERSIONTAG@"
-#define DEF_MONERO_VERSION "0.17.1.3"
+#define DEF_MONERO_VERSION "0.17.1.5"
#define DEF_MONERO_RELEASE_NAME "Oxygen Orion"
#define DEF_MONERO_VERSION_FULL DEF_MONERO_VERSION "-" DEF_MONERO_VERSION_TAG
#define DEF_MONERO_VERSION_IS_RELEASE @VERSION_IS_RELEASE@
diff --git a/tests/core_proxy/core_proxy.h b/tests/core_proxy/core_proxy.h
index 4a41b5002..ecfcc18ae 100644
--- a/tests/core_proxy/core_proxy.h
+++ b/tests/core_proxy/core_proxy.h
@@ -66,9 +66,10 @@ namespace tests
public:
+ virtual bool is_synchronized() const final { return true; }
void on_synchronized(){}
void safesyncmode(const bool){}
- uint64_t get_current_blockchain_height(){return 1;}
+ virtual uint64_t get_current_blockchain_height() const final {return 1;}
void set_target_blockchain_height(uint64_t) {}
bool init(const boost::program_options::variables_map& vm);
bool deinit(){return true;}
diff --git a/tests/unit_tests/levin.cpp b/tests/unit_tests/levin.cpp
index 128d51fb3..22638942d 100644
--- a/tests/unit_tests/levin.cpp
+++ b/tests/unit_tests/levin.cpp
@@ -120,7 +120,12 @@ namespace
{
std::map<cryptonote::relay_method, std::vector<cryptonote::blobdata>> relayed_;
- uint64_t get_target_blockchain_height() const override
+ virtual bool is_synchronized() const final
+ {
+ return false;
+ }
+
+ virtual uint64_t get_current_blockchain_height() const final
{
return 0;
}
diff --git a/tests/unit_tests/node_server.cpp b/tests/unit_tests/node_server.cpp
index 588e91d02..0191e5aa4 100644
--- a/tests/unit_tests/node_server.cpp
+++ b/tests/unit_tests/node_server.cpp
@@ -47,9 +47,10 @@ namespace cryptonote {
class test_core : public cryptonote::i_core_events
{
public:
+ virtual bool is_synchronized() const final { return true; }
void on_synchronized(){}
void safesyncmode(const bool){}
- uint64_t get_current_blockchain_height() const {return 1;}
+ virtual uint64_t get_current_blockchain_height() const final {return 1;}
void set_target_blockchain_height(uint64_t) {}
bool init(const boost::program_options::variables_map& vm) {return true ;}
bool deinit(){return true;}