mirror of
https://github.com/monero-project/monero.git
synced 2024-11-17 08:17:37 +00:00
Merge pull request #7018
a9cd5d9
cryptonote_core: dandelion - use local height or median height if syncing (xiphon)
This commit is contained in:
commit
36d31ba0be
10 changed files with 85 additions and 18 deletions
|
@ -1510,6 +1510,11 @@ namespace cryptonote
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------
|
||||||
|
bool core::is_synchronized() const
|
||||||
|
{
|
||||||
|
return m_pprotocol != nullptr && m_pprotocol->is_synchronized();
|
||||||
|
}
|
||||||
|
//-----------------------------------------------------------------------------------------------
|
||||||
void core::on_synchronized()
|
void core::on_synchronized()
|
||||||
{
|
{
|
||||||
m_miner.on_synchronized();
|
m_miner.on_synchronized();
|
||||||
|
|
|
@ -329,7 +329,7 @@ namespace cryptonote
|
||||||
*
|
*
|
||||||
* @note see Blockchain::get_current_blockchain_height()
|
* @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
|
* @brief get the hash and height of the most recent block
|
||||||
|
@ -637,6 +637,13 @@ namespace cryptonote
|
||||||
*/
|
*/
|
||||||
std::string print_pool(bool short_format) const;
|
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
|
* @copydoc miner::on_synchronized
|
||||||
*
|
*
|
||||||
|
@ -663,7 +670,7 @@ namespace cryptonote
|
||||||
*
|
*
|
||||||
* @param target_blockchain_height the target height
|
* @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
|
* @brief returns the newest hardfork version known to the blockchain
|
||||||
|
|
|
@ -39,7 +39,8 @@ namespace cryptonote
|
||||||
virtual ~i_core_events() noexcept
|
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;
|
virtual void on_transactions_relayed(epee::span<const cryptonote::blobdata> tx_blobs, relay_method tx_relay) = 0;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ namespace cryptonote
|
||||||
bool get_payload_sync_data(CORE_SYNC_DATA& hshd);
|
bool get_payload_sync_data(CORE_SYNC_DATA& hshd);
|
||||||
bool on_callback(cryptonote_connection_context& context);
|
bool on_callback(cryptonote_connection_context& context);
|
||||||
t_core& get_core(){return m_core;}
|
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();
|
void log_connections();
|
||||||
std::list<connection_info> get_connections();
|
std::list<connection_info> get_connections();
|
||||||
const block_queue &get_block_queue() const { return m_block_queue; }
|
const block_queue &get_block_queue() const { return m_block_queue; }
|
||||||
|
|
|
@ -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)");
|
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)
|
if(context.m_state != cryptonote_connection_context::state_normal)
|
||||||
return 1;
|
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");
|
LOG_DEBUG_CC(context, "Received new block while syncing, ignored");
|
||||||
return 1;
|
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)");
|
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)
|
if(context.m_state != cryptonote_connection_context::state_normal)
|
||||||
return 1;
|
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");
|
LOG_DEBUG_CC(context, "Received new block while syncing, ignored");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -929,7 +929,7 @@ namespace cryptonote
|
||||||
// while syncing, core will lock for a long time, so we ignore
|
// while syncing, core will lock for a long time, so we ignore
|
||||||
// those txes as they aren't really needed anyway, and avoid a
|
// those txes as they aren't really needed anyway, and avoid a
|
||||||
// long block before replying
|
// long block before replying
|
||||||
if(!is_synchronized() || m_no_sync)
|
if(!is_synchronized())
|
||||||
{
|
{
|
||||||
LOG_DEBUG_CC(context, "Received new tx while syncing, ignored");
|
LOG_DEBUG_CC(context, "Received new tx while syncing, ignored");
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -40,6 +40,7 @@ namespace cryptonote
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
struct i_cryptonote_protocol
|
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_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 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;
|
//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
|
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)
|
virtual bool relay_block(NOTIFY_NEW_BLOCK::request& arg, cryptonote_connection_context& exclude_context)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -105,8 +105,44 @@ namespace levin
|
||||||
return std::chrono::steady_clock::duration{crypto::rand_range(rep(0), range.count())};
|
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.
|
uint64_t get_median_remote_height(connections& p2p)
|
||||||
std::vector<boost::uuids::uuid> get_out_connections(connections& p2p, uint64_t min_blockchain_height)
|
{
|
||||||
|
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;
|
std::vector<boost::uuids::uuid> outs;
|
||||||
outs.reserve(connection_id_reserve_size);
|
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
|
the reserve call so a strand is not used. Investigate if there is lots
|
||||||
of waiting in here. */
|
of waiting in here. */
|
||||||
|
|
||||||
p2p.foreach_connection([&outs, min_blockchain_height] (detail::p2p_context& context) {
|
p2p.foreach_connection([&outs, blockchain_height] (detail::p2p_context& context) {
|
||||||
if (!context.m_is_income && context.m_remote_blockchain_height >= min_blockchain_height)
|
if (!context.m_is_income && context.m_remote_blockchain_height >= blockchain_height)
|
||||||
outs.emplace_back(context.m_connection_id);
|
outs.emplace_back(context.m_connection_id);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
MDEBUG("Found " << outs.size() << " out connections having height >= " << blockchain_height);
|
||||||
return outs;
|
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)
|
std::string make_tx_payload(std::vector<blobdata>&& txs, const bool pad, const bool fluff)
|
||||||
{
|
{
|
||||||
NOTIFY_NEW_TRANSACTIONS::request request{};
|
NOTIFY_NEW_TRANSACTIONS::request request{};
|
||||||
|
@ -540,7 +582,7 @@ namespace levin
|
||||||
}
|
}
|
||||||
|
|
||||||
// connection list may be outdated, try again
|
// 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");
|
MERROR("Unable to send transaction(s) via Dandelion++ stem");
|
||||||
|
@ -644,7 +686,7 @@ namespace levin
|
||||||
{
|
{
|
||||||
channel.active = nullptr;
|
channel.active = nullptr;
|
||||||
channel.connection = boost::uuids::nil_uuid();
|
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);
|
auto connections = get_out_connections(*zone_->p2p, height);
|
||||||
if (connections.empty())
|
if (connections.empty())
|
||||||
|
@ -680,7 +722,7 @@ namespace levin
|
||||||
|
|
||||||
const bool fluffing = crypto::rand_idx(unsigned(100)) < CRYPTONOTE_DANDELIONPP_FLUFF_PROBABILITY;
|
const bool fluffing = crypto::rand_idx(unsigned(100)) < CRYPTONOTE_DANDELIONPP_FLUFF_PROBABILITY;
|
||||||
const auto start = std::chrono::steady_clock::now();
|
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(
|
zone_->strand.dispatch(
|
||||||
change_channels{zone_, net::dandelionpp::connection_map{std::move(connections), count_}, fluffing}
|
change_channels{zone_, net::dandelionpp::connection_map{std::move(connections), count_}, fluffing}
|
||||||
);
|
);
|
||||||
|
@ -731,7 +773,7 @@ namespace levin
|
||||||
return;
|
return;
|
||||||
|
|
||||||
zone_->strand.dispatch(
|
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_)}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,9 +66,10 @@ namespace tests
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
virtual bool is_synchronized() const final { return true; }
|
||||||
void on_synchronized(){}
|
void on_synchronized(){}
|
||||||
void safesyncmode(const bool){}
|
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) {}
|
void set_target_blockchain_height(uint64_t) {}
|
||||||
bool init(const boost::program_options::variables_map& vm);
|
bool init(const boost::program_options::variables_map& vm);
|
||||||
bool deinit(){return true;}
|
bool deinit(){return true;}
|
||||||
|
|
|
@ -120,7 +120,12 @@ namespace
|
||||||
{
|
{
|
||||||
std::map<cryptonote::relay_method, std::vector<cryptonote::blobdata>> relayed_;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,9 +47,10 @@ namespace cryptonote {
|
||||||
class test_core : public cryptonote::i_core_events
|
class test_core : public cryptonote::i_core_events
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
virtual bool is_synchronized() const final { return true; }
|
||||||
void on_synchronized(){}
|
void on_synchronized(){}
|
||||||
void safesyncmode(const bool){}
|
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) {}
|
void set_target_blockchain_height(uint64_t) {}
|
||||||
bool init(const boost::program_options::variables_map& vm) {return true ;}
|
bool init(const boost::program_options::variables_map& vm) {return true ;}
|
||||||
bool deinit(){return true;}
|
bool deinit(){return true;}
|
||||||
|
|
Loading…
Reference in a new issue