From 329082d81b8190f658891c359ab1629d39e8e02f Mon Sep 17 00:00:00 2001 From: Abner Zheng Date: Thu, 29 Feb 2024 01:53:45 +0800 Subject: [PATCH] feat: Implement eth68 announcement metrics, track entries by TxType (#6786) Co-authored-by: Emilia Hane --- crates/net/network/src/metrics.rs | 59 ++++++++++++++++++ .../network/src/transactions/validation.rs | 62 +++++++++++++------ 2 files changed, 102 insertions(+), 19 deletions(-) diff --git a/crates/net/network/src/metrics.rs b/crates/net/network/src/metrics.rs index fe3936d89..45e249071 100644 --- a/crates/net/network/src/metrics.rs +++ b/crates/net/network/src/metrics.rs @@ -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); + } +} diff --git a/crates/net/network/src/transactions/validation.rs b/crates/net/network/src/transactions/validation.rs index 585bb3b73..1495e4055 100644 --- a/crates/net/network/src/transactions/validation.rs +++ b/crates/net/network/src/transactions/validation.rs @@ -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); /// 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()); } }