dncurrency/nano/node/local_block_broadcaster.hpp
2025-01-14 22:35:36 +01:00

125 lines
3.2 KiB
C++

#pragma once
#include <nano/lib/blocks.hpp>
#include <nano/lib/interval.hpp>
#include <nano/lib/locks.hpp>
#include <nano/lib/processing_queue.hpp>
#include <nano/lib/rate_limiting.hpp>
#include <nano/node/block_processor.hpp>
#include <nano/node/fwd.hpp>
#include <nano/secure/common.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/mem_fun.hpp>
#include <boost/multi_index/ordered_index.hpp>
#include <boost/multi_index/sequenced_index.hpp>
#include <boost/multi_index_container.hpp>
#include <memory>
#include <thread>
#include <unordered_set>
namespace mi = boost::multi_index;
namespace nano
{
class local_block_broadcaster_config final
{
public:
explicit local_block_broadcaster_config (nano::network_constants const & network)
{
if (network.is_dev_network ())
{
rebroadcast_interval = 1s;
cleanup_interval = 1s;
}
}
// TODO: Serialization & deserialization
public:
std::size_t max_size{ 1024 * 8 };
std::chrono::seconds rebroadcast_interval{ 3 };
std::chrono::seconds max_rebroadcast_interval{ 60 };
std::size_t broadcast_rate_limit{ 32 };
double broadcast_rate_burst_ratio{ 3 };
std::chrono::seconds cleanup_interval{ 60 };
};
/**
* Broadcasts blocks to the network
* Tracks local blocks for more aggressive propagation
*/
class local_block_broadcaster final
{
public:
local_block_broadcaster (local_block_broadcaster_config const &, nano::node &, nano::ledger_notifications &, nano::network &, nano::confirming_set &, nano::stats &, nano::logger &, bool enabled = false);
~local_block_broadcaster ();
void start ();
void stop ();
bool contains (nano::block_hash const &) const;
size_t size () const;
nano::container_info container_info () const;
private:
void run ();
void run_broadcasts (nano::unique_lock<nano::mutex> &);
void cleanup (nano::unique_lock<nano::mutex> &);
std::chrono::milliseconds rebroadcast_interval (unsigned rebroadcasts) const;
private: // Dependencies
local_block_broadcaster_config const & config;
nano::node & node;
nano::ledger_notifications & ledger_notifications;
nano::network & network;
nano::confirming_set & confirming_set;
nano::stats & stats;
nano::logger & logger;
private:
struct local_entry
{
std::shared_ptr<nano::block> block;
std::chrono::steady_clock::time_point arrival;
std::chrono::steady_clock::time_point last_broadcast{};
std::chrono::steady_clock::time_point next_broadcast{};
unsigned rebroadcasts{ 0 };
nano::block_hash hash () const
{
return block->hash ();
}
};
// clang-format off
class tag_sequenced {};
class tag_hash {};
class tag_broadcast {};
using ordered_locals = boost::multi_index_container<local_entry,
mi::indexed_by<
mi::sequenced<mi::tag<tag_sequenced>>,
mi::hashed_unique<mi::tag<tag_hash>,
mi::const_mem_fun<local_entry, nano::block_hash, &local_entry::hash>>,
mi::ordered_non_unique<mi::tag<tag_broadcast>,
mi::member<local_entry, std::chrono::steady_clock::time_point, &local_entry::next_broadcast>>
>>;
// clang-format on
ordered_locals local_blocks;
private:
bool enabled{ false };
nano::rate_limiter limiter;
nano::interval cleanup_interval;
std::atomic<bool> stopped{ false };
nano::condition_variable condition;
mutable nano::mutex mutex;
std::thread thread;
};
}