From 6c8b9e482d79cc16bff196c21fffa4d4ff962c02 Mon Sep 17 00:00:00 2001 From: shana Date: Thu, 27 Feb 2025 21:04:43 +1100 Subject: [PATCH] Add metrics for reverted transactions and builder balance in exex (#451) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## 📝 Summary ## 💡 Motivation and Context --- ## ✅ I have completed the following steps: * [x] Run `make lint` * [x] Run `make test` * [x] Added tests (if applicable) --- crates/op-rbuilder/src/metrics.rs | 12 +++++ crates/op-rbuilder/src/monitoring.rs | 65 ++++++++++++++++++++++++++-- 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/crates/op-rbuilder/src/metrics.rs b/crates/op-rbuilder/src/metrics.rs index 5f8784f65..4451d0b5d 100644 --- a/crates/op-rbuilder/src/metrics.rs +++ b/crates/op-rbuilder/src/metrics.rs @@ -4,6 +4,8 @@ use reth_metrics::{metrics::Counter, metrics::Gauge, metrics::Histogram, Metrics #[derive(Metrics, Clone)] #[metrics(scope = "op_rbuilder")] pub struct OpRBuilderMetrics { + /// Builder balance of the last block + pub builder_balance: Gauge, /// Number of builder landed blocks pub builder_landed_blocks: Gauge, /// Last built block height @@ -40,9 +42,15 @@ pub struct OpRBuilderMetrics { pub tx_simulation_duration: Histogram, /// Byte size of transactions pub tx_byte_size: Histogram, + /// Number of reverted transactions + pub num_reverted_tx: Counter, } impl OpRBuilderMetrics { + pub fn inc_num_reverted_tx(&self, num_reverted_tx: usize) { + self.num_reverted_tx.increment(num_reverted_tx as u64); + } + pub fn inc_builder_landed_blocks(&self) { self.builder_landed_blocks.increment(1); } @@ -58,4 +66,8 @@ impl OpRBuilderMetrics { pub fn set_last_landed_block_height(&self, height: u64) { self.last_landed_block_height.set(height as f64); } + + pub fn set_builder_balance(&self, balance: f64) { + self.builder_balance.set(balance); + } } diff --git a/crates/op-rbuilder/src/monitoring.rs b/crates/op-rbuilder/src/monitoring.rs index 9aa51e659..f94c27541 100644 --- a/crates/op-rbuilder/src/monitoring.rs +++ b/crates/op-rbuilder/src/monitoring.rs @@ -1,13 +1,14 @@ use alloy_consensus::{Transaction, TxReceipt}; +use alloy_primitives::U256; use futures_util::{Stream, StreamExt, TryStreamExt}; use reth::core::primitives::SignedTransaction; use reth_chain_state::CanonStateNotification; use reth_exex::{ExExContext, ExExEvent}; use reth_node_api::{FullNodeComponents, NodeTypes}; -use reth_optimism_primitives::{OpPrimitives, OpTransactionSigned}; +use reth_optimism_primitives::{OpPrimitives, OpReceipt, OpTransactionSigned}; use reth_primitives::{Block, RecoveredBlock}; -use reth_provider::Chain; -use tracing::info; +use reth_provider::{Chain, ExecutionOutcome}; +use tracing::{info, warn}; use crate::{metrics::OpRBuilderMetrics, tx_signer::Signer}; @@ -16,6 +17,7 @@ const OP_BUILDER_TX_PREFIX: &[u8] = b"Block Number:"; pub struct Monitoring { builder_signer: Option, metrics: OpRBuilderMetrics, + execution_outcome: ExecutionOutcome, } impl Monitoring { @@ -23,6 +25,7 @@ impl Monitoring { Self { builder_signer, metrics: Default::default(), + execution_outcome: Default::default(), } } @@ -31,7 +34,6 @@ impl Monitoring { where Node: FullNodeComponents>, { - // TODO: add builder balance monitoring // Process all new chain state notifications while let Some(notification) = ctx.notifications.try_next().await? { if let Some(reverted_chain) = notification.reverted_chain() { @@ -83,6 +85,27 @@ impl Monitoring { } } + let num_reverted_tx = decode_chain_into_reverted_txs(chain); + self.metrics.inc_num_reverted_tx(num_reverted_tx); + + self.execution_outcome + .extend(chain.execution_outcome().clone()); + let builder_balance = + decode_state_into_builder_balance(&self.execution_outcome, self.builder_signer) + .and_then(|balance| { + balance + .to_string() + .parse::() + .map_err(|e| { + warn!("Failed to parse builder balance: {}", e); + e + }) + .ok() + }); + if let Some(balance) = builder_balance { + self.metrics.set_builder_balance(balance); + } + Ok(()) } @@ -91,6 +114,7 @@ impl Monitoring { /// This function decodes all transactions in the block, updates the metrics for builder built blocks async fn revert(&mut self, chain: &Chain) -> eyre::Result<()> { info!("Processing new chain revert"); + self.execution_outcome.revert_to(chain.first().number - 1); let mut blocks = decode_chain_into_builder_txs(chain, self.builder_signer); // Reverse the order of txs to start reverting from the tip blocks.reverse(); @@ -140,3 +164,36 @@ fn decode_chain_into_builder_txs( }) .collect() } + +/// Decode chain of blocks and check if any transactions has reverted +fn decode_chain_into_reverted_txs(chain: &Chain) -> usize { + chain + // Get all blocks and receipts + .blocks_and_receipts() + // Get all receipts + .map(|(block, receipts)| { + block + .body() + .transactions + .iter() + .zip(receipts.iter()) + .filter(|(_, receipt)| !receipt.status()) + .count() + }) + .sum() +} + +/// Decode state and find the last builder balance +fn decode_state_into_builder_balance( + execution_outcome: &ExecutionOutcome, + builder_signer: Option, +) -> Option { + builder_signer.and_then(|signer| { + execution_outcome + .bundle + .state + .iter() + .find(|(address, _)| *address == &signer.address) + .and_then(|(_, account)| account.info.as_ref().map(|info| info.balance)) + }) +}