discv5/discv5_client.hpp¶
Namespaces¶
| Name |
|---|
| discv5 |
Classes¶
| Name | |
|---|---|
| class | discv5::discv5_client Discovery v5 protocol client. |
Types¶
| Name | |
|---|---|
| using asio::ip::udp | udp |
| using std::shared_ptr< spdlog::logger > | Logger |
Functions¶
| Name | |
|---|---|
| std::shared_ptr< spdlog::logger > | createLogger(const std::string & tag, const std::string & basepath ="") Create a logger instance. |
Types Documentation¶
using udp¶
using Logger¶
Functions Documentation¶
function createLogger¶
std::shared_ptr< spdlog::logger > createLogger(
const std::string & tag,
const std::string & basepath =""
)
Create a logger instance.
Parameters:
- tag Tagging name for identifying logger.
- basepath Optional base path for log output (platform dependent).
Return: Logger object.
Source code¶
// Copyright 2025 GeniusVentures
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <array>
#include <atomic>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>
#include <base/rlp-logger.hpp>
#include <discv5/discv5_crawler.hpp>
#include <discv5/discv5_error.hpp>
#include <discv5/discv5_types.hpp>
namespace discv5
{
using rlp::base::Logger;
using rlp::base::createLogger;
namespace asio = boost::asio;
using udp = asio::ip::udp;
// ---------------------------------------------------------------------------
// discv5_client
// ---------------------------------------------------------------------------
class discv5_client
{
public:
explicit discv5_client(asio::io_context& io_context, const discv5Config& config);
~discv5_client();
// Non-copyable, non-movable.
discv5_client(const discv5_client&) = delete;
discv5_client& operator=(const discv5_client&) = delete;
discv5_client(discv5_client&&) = delete;
discv5_client& operator=(discv5_client&&) = delete;
// -----------------------------------------------------------------------
// Configuration
// -----------------------------------------------------------------------
void add_bootnode(const std::string& enr_uri) noexcept;
void set_peer_discovered_callback(PeerDiscoveredCallback callback) noexcept;
void set_error_callback(ErrorCallback callback) noexcept;
// -----------------------------------------------------------------------
// Lifecycle
// -----------------------------------------------------------------------
VoidResult start() noexcept;
void stop() noexcept;
// -----------------------------------------------------------------------
// Accessors
// -----------------------------------------------------------------------
[[nodiscard]] CrawlerStats stats() const noexcept;
[[nodiscard]] const NodeId& local_node_id() const noexcept;
[[nodiscard]] bool is_running() const noexcept;
[[nodiscard]] uint16_t bound_port() const noexcept;
[[nodiscard]] size_t received_packet_count() const noexcept;
[[nodiscard]] size_t dropped_undersized_packet_count() const noexcept;
[[nodiscard]] size_t send_findnode_failure_count() const noexcept;
[[nodiscard]] size_t whoareyou_packet_count() const noexcept;
[[nodiscard]] size_t handshake_packet_count() const noexcept;
[[nodiscard]] size_t outbound_handshake_attempt_count() const noexcept;
[[nodiscard]] size_t outbound_handshake_failure_count() const noexcept;
[[nodiscard]] size_t inbound_handshake_reject_auth_count() const noexcept;
[[nodiscard]] size_t inbound_handshake_reject_challenge_count() const noexcept;
[[nodiscard]] size_t inbound_handshake_reject_record_count() const noexcept;
[[nodiscard]] size_t inbound_handshake_reject_crypto_count() const noexcept;
[[nodiscard]] size_t inbound_handshake_reject_decrypt_count() const noexcept;
[[nodiscard]] size_t inbound_handshake_seen_count() const noexcept;
[[nodiscard]] size_t inbound_message_seen_count() const noexcept;
[[nodiscard]] size_t inbound_message_decrypt_fail_count() const noexcept;
[[nodiscard]] size_t nodes_packet_count() const noexcept;
private:
// -----------------------------------------------------------------------
// Internal coroutines
// -----------------------------------------------------------------------
void receive_loop(asio::yield_context yield);
void crawler_loop(asio::yield_context yield);
void handle_packet(
const uint8_t* data,
size_t length,
const udp::endpoint& sender) noexcept;
VoidResult send_findnode(const ValidatedPeer& peer, asio::yield_context yield);
VoidResult send_packet(
const std::vector<uint8_t>& packet,
const ValidatedPeer& peer,
asio::yield_context yield);
VoidResult send_whoareyou(
const udp::endpoint& sender,
const std::array<uint8_t, kKeccak256Bytes>& remote_node_addr,
const std::array<uint8_t, kGcmNonceBytes>& request_nonce,
asio::yield_context yield);
VoidResult handle_findnode_request(
const std::vector<uint8_t>& req_id,
const udp::endpoint& sender,
asio::yield_context yield);
Result<std::vector<uint8_t>> build_local_enr() noexcept;
// -----------------------------------------------------------------------
// Members
// -----------------------------------------------------------------------
struct SessionState
{
std::array<uint8_t, 16U> write_key{};
std::array<uint8_t, 16U> read_key{};
std::array<uint8_t, kKeccak256Bytes> remote_node_addr{};
NodeId remote_node_id{};
std::vector<uint8_t> last_req_id{};
};
struct PendingRequest
{
ValidatedPeer peer{};
std::vector<uint8_t> req_id{};
std::array<uint8_t, kGcmNonceBytes> request_nonce{};
std::vector<uint8_t> challenge_data{};
std::array<uint8_t, kWhoareyouIdNonceBytes> id_nonce{};
uint64_t record_seq{};
bool have_challenge{false};
};
struct ChallengeState
{
std::array<uint8_t, kKeccak256Bytes> remote_node_addr{};
std::vector<uint8_t> challenge_data{};
std::array<uint8_t, kGcmNonceBytes> request_nonce{};
std::array<uint8_t, kWhoareyouIdNonceBytes> id_nonce{};
uint64_t record_seq{};
};
asio::io_context& io_context_;
discv5Config config_;
udp::socket socket_;
discv5_crawler crawler_;
Logger logger_ = createLogger("discv5");
std::unordered_map<std::string, SessionState> sessions_;
std::unordered_map<std::string, PendingRequest> pending_requests_;
std::unordered_map<std::string, ChallengeState> sent_challenges_;
std::atomic<bool> running_{false};
std::atomic<size_t> received_packets_{0U};
std::atomic<size_t> dropped_undersized_packets_{0U};
std::atomic<size_t> send_findnode_failures_{0U};
std::atomic<size_t> whoareyou_packets_{0U};
std::atomic<size_t> handshake_packets_{0U};
std::atomic<size_t> outbound_handshake_attempts_{0U};
std::atomic<size_t> outbound_handshake_failures_{0U};
std::atomic<size_t> inbound_handshake_reject_auth_{0U};
std::atomic<size_t> inbound_handshake_reject_challenge_{0U};
std::atomic<size_t> inbound_handshake_reject_record_{0U};
std::atomic<size_t> inbound_handshake_reject_crypto_{0U};
std::atomic<size_t> inbound_handshake_reject_decrypt_{0U};
std::atomic<size_t> inbound_handshake_seen_{0U};
std::atomic<size_t> inbound_message_seen_{0U};
std::atomic<size_t> inbound_message_decrypt_fail_{0U};
std::atomic<size_t> nodes_packets_{0U};
};
} // namespace discv5
Updated on 2026-04-13 at 23:22:46 -0700