mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
feat: Implement eth68 announcement metrics, track entries by TxType (#6786)
Co-authored-by: Emilia Hane <emiliaha95@gmail.com>
This commit is contained in:
@ -1,8 +1,10 @@
|
||||
use metrics::Histogram;
|
||||
use reth_eth_wire::DisconnectReason;
|
||||
use reth_metrics::{
|
||||
metrics::{Counter, Gauge},
|
||||
Metrics,
|
||||
};
|
||||
use reth_primitives::TxType;
|
||||
|
||||
/// Scope for monitoring transactions sent from the manager to the tx manager
|
||||
pub(crate) const NETWORK_POOL_TRANSACTIONS_SCOPE: &str = "network.pool.transactions";
|
||||
@ -244,3 +246,60 @@ pub struct EthRequestHandlerMetrics {
|
||||
/// Number of received bodies requests
|
||||
pub(crate) received_bodies_requests: Counter,
|
||||
}
|
||||
|
||||
/// Eth67 announcement metrics, track entries by TxType
|
||||
#[derive(Metrics)]
|
||||
#[metrics(scope = "network.transaction_fetcher")]
|
||||
pub struct AnnouncedTxTypesMetrics {
|
||||
/// Histogram for tracking frequency of legacy transaction type
|
||||
pub(crate) legacy: Histogram,
|
||||
|
||||
/// Histogram for tracking frequency of EIP-2930 transaction type
|
||||
pub(crate) eip2930: Histogram,
|
||||
|
||||
/// Histogram for tracking frequency of EIP-1559 transaction type
|
||||
pub(crate) eip1559: Histogram,
|
||||
|
||||
/// Histogram for tracking frequency of EIP-4844 transaction type
|
||||
pub(crate) eip4844: Histogram,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct TxTypesCounter {
|
||||
pub(crate) legacy: usize,
|
||||
pub(crate) eip2930: usize,
|
||||
pub(crate) eip1559: usize,
|
||||
pub(crate) eip4844: usize,
|
||||
}
|
||||
|
||||
impl TxTypesCounter {
|
||||
pub(crate) fn increase_by_tx_type(&mut self, tx_type: TxType) {
|
||||
match tx_type {
|
||||
TxType::Legacy => {
|
||||
self.legacy += 1;
|
||||
}
|
||||
TxType::EIP2930 => {
|
||||
self.eip2930 += 1;
|
||||
}
|
||||
TxType::EIP1559 => {
|
||||
self.eip1559 += 1;
|
||||
}
|
||||
TxType::EIP4844 => {
|
||||
self.eip4844 += 1;
|
||||
}
|
||||
#[cfg(feature = "optimism")]
|
||||
TxType::DEPOSIT => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AnnouncedTxTypesMetrics {
|
||||
/// Update metrics during announcement validation, by examining each announcement entry based on
|
||||
/// TxType
|
||||
pub(crate) fn update_eth68_announcement_metrics(&self, tx_types_counter: TxTypesCounter) {
|
||||
self.legacy.record(tx_types_counter.legacy as f64);
|
||||
self.eip2930.record(tx_types_counter.eip2930 as f64);
|
||||
self.eip1559.record(tx_types_counter.eip1559 as f64);
|
||||
self.eip4844.record(tx_types_counter.eip4844 as f64);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,9 +2,10 @@
|
||||
//! and [`NewPooledTransactionHashes68`](reth_eth_wire::NewPooledTransactionHashes68)
|
||||
//! announcements. Validation and filtering of announcements is network dependent.
|
||||
|
||||
use std::{fmt, mem};
|
||||
use std::{fmt, fmt::Display, mem};
|
||||
|
||||
use derive_more::{Deref, DerefMut, Display};
|
||||
use crate::metrics::{AnnouncedTxTypesMetrics, TxTypesCounter};
|
||||
use derive_more::{Deref, DerefMut};
|
||||
use reth_eth_wire::{
|
||||
DedupPayload, Eth68TxMetadata, HandleMempoolData, PartiallyValidData, ValidAnnouncementData,
|
||||
MAX_MESSAGE_SIZE,
|
||||
@ -22,7 +23,13 @@ pub trait ValidateTx68 {
|
||||
/// entry. Returns [`ValidationOutcome`] which signals to the caller wether to fetch the
|
||||
/// transaction or wether to drop it, and wether the sender of the announcement should be
|
||||
/// penalized.
|
||||
fn should_fetch(&self, ty: u8, hash: &TxHash, size: usize) -> ValidationOutcome;
|
||||
fn should_fetch(
|
||||
&self,
|
||||
ty: u8,
|
||||
hash: &TxHash,
|
||||
size: usize,
|
||||
tx_types_counter: &mut TxTypesCounter,
|
||||
) -> ValidationOutcome;
|
||||
|
||||
/// Returns the reasonable maximum encoded transaction length configured for this network, if
|
||||
/// any. This property is not spec'ed out but can be inferred by looking how much data can be
|
||||
@ -137,13 +144,27 @@ pub enum FilterOutcome {
|
||||
pub struct MessageFilter<N = EthMessageFilter>(N);
|
||||
|
||||
/// Filter for announcements containing EIP [`TxType`]s.
|
||||
#[derive(Debug, Display, Default)]
|
||||
pub struct EthMessageFilter;
|
||||
#[derive(Debug, Default)]
|
||||
pub struct EthMessageFilter {
|
||||
announced_tx_types_metrics: AnnouncedTxTypesMetrics,
|
||||
}
|
||||
|
||||
impl Display for EthMessageFilter {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "EthMessageFilter")
|
||||
}
|
||||
}
|
||||
|
||||
impl PartiallyFilterMessage for EthMessageFilter {}
|
||||
|
||||
impl ValidateTx68 for EthMessageFilter {
|
||||
fn should_fetch(&self, ty: u8, hash: &TxHash, size: usize) -> ValidationOutcome {
|
||||
fn should_fetch(
|
||||
&self,
|
||||
ty: u8,
|
||||
hash: &TxHash,
|
||||
size: usize,
|
||||
tx_types_counter: &mut TxTypesCounter,
|
||||
) -> ValidationOutcome {
|
||||
//
|
||||
// 1. checks if tx type is valid value for this network
|
||||
//
|
||||
@ -154,13 +175,14 @@ impl ValidateTx68 for EthMessageFilter {
|
||||
ty=ty,
|
||||
size=size,
|
||||
hash=%hash,
|
||||
network=%Self,
|
||||
network=%self,
|
||||
"invalid tx type in eth68 announcement"
|
||||
);
|
||||
|
||||
return ValidationOutcome::ReportPeer
|
||||
}
|
||||
};
|
||||
tx_types_counter.increase_by_tx_type(tx_type);
|
||||
|
||||
//
|
||||
// 2. checks if tx's encoded length is within limits for this network
|
||||
@ -175,7 +197,7 @@ impl ValidateTx68 for EthMessageFilter {
|
||||
size=size,
|
||||
hash=%hash,
|
||||
strict_min_encoded_tx_length=strict_min_encoded_tx_length,
|
||||
network=%Self,
|
||||
network=%self,
|
||||
"invalid tx size in eth68 announcement"
|
||||
);
|
||||
|
||||
@ -190,7 +212,7 @@ impl ValidateTx68 for EthMessageFilter {
|
||||
hash=%hash,
|
||||
reasonable_min_encoded_tx_length=reasonable_min_encoded_tx_length,
|
||||
strict_min_encoded_tx_length=self.strict_min_encoded_tx_length(tx_type),
|
||||
network=%Self,
|
||||
network=%self,
|
||||
"tx size in eth68 announcement, is unreasonably small"
|
||||
);
|
||||
|
||||
@ -207,7 +229,7 @@ impl ValidateTx68 for EthMessageFilter {
|
||||
hash=%hash,
|
||||
reasonable_max_encoded_tx_length=reasonable_max_encoded_tx_length,
|
||||
strict_max_encoded_tx_length=self.strict_max_encoded_tx_length(tx_type),
|
||||
network=%Self,
|
||||
network=%self,
|
||||
"tx size in eth68 announcement, is unreasonably large"
|
||||
);
|
||||
|
||||
@ -256,11 +278,12 @@ impl FilterAnnouncement for EthMessageFilter {
|
||||
{
|
||||
trace!(target: "net::tx::validation",
|
||||
msg=?*msg,
|
||||
network=%Self,
|
||||
network=%self,
|
||||
"validating eth68 announcement data.."
|
||||
);
|
||||
|
||||
let mut should_report_peer = false;
|
||||
let mut tx_types_counter = TxTypesCounter::default();
|
||||
|
||||
// checks if eth68 announcement metadata is valid
|
||||
//
|
||||
@ -278,7 +301,7 @@ impl FilterAnnouncement for EthMessageFilter {
|
||||
return false
|
||||
};
|
||||
|
||||
match self.should_fetch(*ty, hash, *size) {
|
||||
match self.should_fetch(*ty, hash, *size, &mut tx_types_counter) {
|
||||
ValidationOutcome::Fetch => true,
|
||||
ValidationOutcome::Ignore => false,
|
||||
ValidationOutcome::ReportPeer => {
|
||||
@ -287,6 +310,7 @@ impl FilterAnnouncement for EthMessageFilter {
|
||||
}
|
||||
}
|
||||
});
|
||||
self.announced_tx_types_metrics.update_eth68_announcement_metrics(tx_types_counter);
|
||||
(
|
||||
if should_report_peer { FilterOutcome::ReportPeer } else { FilterOutcome::Ok },
|
||||
ValidAnnouncementData::from_partially_valid_data(msg),
|
||||
@ -299,7 +323,7 @@ impl FilterAnnouncement for EthMessageFilter {
|
||||
) -> (FilterOutcome, ValidAnnouncementData) {
|
||||
trace!(target: "net::tx::validation",
|
||||
hashes=?*partially_valid_data,
|
||||
network=%Self,
|
||||
network=%self,
|
||||
"validating eth66 announcement data.."
|
||||
);
|
||||
|
||||
@ -323,7 +347,7 @@ mod test {
|
||||
|
||||
let announcement = NewPooledTransactionHashes68 { types, sizes, hashes };
|
||||
|
||||
let filter = EthMessageFilter;
|
||||
let filter = EthMessageFilter::default();
|
||||
|
||||
let (outcome, _partially_valid_data) = filter.partially_filter_valid_entries(announcement);
|
||||
|
||||
@ -350,7 +374,7 @@ mod test {
|
||||
hashes: hashes.clone(),
|
||||
};
|
||||
|
||||
let filter = EthMessageFilter;
|
||||
let filter = EthMessageFilter::default();
|
||||
|
||||
let (outcome, partially_valid_data) = filter.partially_filter_valid_entries(announcement);
|
||||
|
||||
@ -390,7 +414,7 @@ mod test {
|
||||
hashes: hashes.clone(),
|
||||
};
|
||||
|
||||
let filter = EthMessageFilter;
|
||||
let filter = EthMessageFilter::default();
|
||||
|
||||
let (outcome, partially_valid_data) = filter.partially_filter_valid_entries(announcement);
|
||||
|
||||
@ -433,7 +457,7 @@ mod test {
|
||||
hashes: hashes.clone(),
|
||||
};
|
||||
|
||||
let filter = EthMessageFilter;
|
||||
let filter = EthMessageFilter::default();
|
||||
|
||||
let (outcome, partially_valid_data) = filter.partially_filter_valid_entries(announcement);
|
||||
|
||||
@ -491,8 +515,8 @@ mod test {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_derive_more_display_for_zst() {
|
||||
let filter = EthMessageFilter;
|
||||
fn test_display_for_zst() {
|
||||
let filter = EthMessageFilter::default();
|
||||
assert_eq!("EthMessageFilter", &filter.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user