Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions crates/apollo_dashboard/resources/dev_grafana.json
Original file line number Diff line number Diff line change
Expand Up @@ -1508,6 +1508,47 @@
],
"collapsed": true
},
"SNIP-35": {
"panels": [
{
"title": "SNIP-35 fee_actual (GFri)",
"description": "Median of recent fee_proposals over the sliding window, in GFri",
"type": "timeseries",
"exprs": [
"snip35_fee_actual{cluster=~\"$cluster\", namespace=~\"$namespace\", pod=~\"$pod\"} / 1e9"
],
"extra_params": {}
},
{
"title": "SNIP-35 fee_proposal (GFri)",
"description": "fee_proposal this node published in the latest block, in GFri",
"type": "timeseries",
"exprs": [
"snip35_fee_proposal{cluster=~\"$cluster\", namespace=~\"$namespace\", pod=~\"$pod\"} / 1e9"
],
"extra_params": {}
},
{
"title": "SNIP-35 fee_target (GFri)",
"description": "fee_target computed from the STRK/USD oracle, in GFri",
"type": "timeseries",
"exprs": [
"snip35_fee_target{cluster=~\"$cluster\", namespace=~\"$namespace\", pod=~\"$pod\"} / 1e9"
],
"extra_params": {}
},
{
"title": "SNIP-35 STRK/USD rate (USD)",
"description": "STRK/USD rate from the oracle, in USD (raw value has 18 decimals)",
"type": "timeseries",
"exprs": [
"snip35_strk_usd_rate{cluster=~\"$cluster\", namespace=~\"$namespace\", pod=~\"$pod\"} / 1e18"
],
"extra_params": {}
}
],
"collapsed": true
},
"Blockifier": {
"panels": [
{
Expand Down
2 changes: 2 additions & 0 deletions crates/apollo_dashboard/src/dashboard_definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ use crate::panels::consensus::{
get_panel_consensus_block_number_diff_from_sync,
get_panel_consensus_decisions_reached_as_proposer_counter,
get_panel_consensus_round,
get_snip35_row,
};
use crate::panels::gateway::{get_gateway_row, get_panel_gateway_add_tx_failure_by_reason};
use crate::panels::http_server::{
Expand Down Expand Up @@ -100,6 +101,7 @@ pub fn get_apollo_dashboard() -> Dashboard {
get_upgrade_row(),
get_l1_events_row(),
get_l1_gas_price_row(),
get_snip35_row(),
get_blockifier_row(),
get_compile_to_casm_row(),
get_consensus_p2p_row(),
Expand Down
52 changes: 52 additions & 0 deletions crates/apollo_dashboard/src/panels/consensus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,10 @@ use apollo_consensus_orchestrator::metrics::{
LABEL_BUILD_PROPOSAL_FAILURE_REASON,
LABEL_CENDE_FAILURE_REASON,
LABEL_VALIDATE_PROPOSAL_FAILURE_REASON,
SNIP35_FEE_ACTUAL,
SNIP35_FEE_PROPOSAL,
SNIP35_FEE_TARGET,
SNIP35_STRK_USD_RATE,
};
use apollo_metrics::metrics::MetricQueryName;
use apollo_network::metrics::{LABEL_NAME_BROADCAST_DROP_REASON, LABEL_NAME_EVENT_TYPE};
Expand Down Expand Up @@ -708,6 +712,54 @@ pub(crate) fn get_cende_row() -> Row {
)
}

fn get_panel_snip35_fee_actual() -> Panel {
Panel::new(
"SNIP-35 fee_actual (GFri)",
"Median of recent fee_proposals over the sliding window, in GFri",
format!("{} / 1e9", SNIP35_FEE_ACTUAL.get_name_with_filter()),
PanelType::TimeSeries,
)
}

fn get_panel_snip35_fee_proposal() -> Panel {
Panel::new(
"SNIP-35 fee_proposal (GFri)",
"fee_proposal this node published in the latest block, in GFri",
format!("{} / 1e9", SNIP35_FEE_PROPOSAL.get_name_with_filter()),
PanelType::TimeSeries,
)
}

fn get_panel_snip35_fee_target() -> Panel {
Panel::new(
"SNIP-35 fee_target (GFri)",
"fee_target computed from the STRK/USD oracle, in GFri",
format!("{} / 1e9", SNIP35_FEE_TARGET.get_name_with_filter()),
PanelType::TimeSeries,
)
}

fn get_panel_snip35_strk_usd_rate() -> Panel {
Panel::new(
"SNIP-35 STRK/USD rate (USD)",
"STRK/USD rate from the oracle, in USD (raw value has 18 decimals)",
format!("{} / 1e18", SNIP35_STRK_USD_RATE.get_name_with_filter()),
PanelType::TimeSeries,
)
}

pub(crate) fn get_snip35_row() -> Row {
Row::new(
"SNIP-35",
vec![
get_panel_snip35_fee_actual(),
get_panel_snip35_fee_proposal(),
get_panel_snip35_fee_target(),
get_panel_snip35_strk_usd_rate(),
],
)
}

pub(crate) fn get_consensus_p2p_row() -> Row {
Row::new(
"ConsensusP2p",
Expand Down
2 changes: 1 addition & 1 deletion crates/apollo_l1_gas_price/src/exchange_rate_oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,7 @@ impl ExchangeRateOracleClientTrait for ExchangeRateOracleClient {
/// - `price`: a hexadecimal string representing the price.
/// - `decimals`: a `u64` value, must be equal to `EXCHANGE_RATE_DECIMALS`.
#[instrument(skip(self))]
async fn eth_to_fri_rate(&self, timestamp: u64) -> Result<u128, ExchangeRateOracleClientError> {
async fn fetch_rate(&self, timestamp: u64) -> Result<u128, ExchangeRateOracleClientError> {
const NUMBER_OF_TIMESTAMPS_BACK: u64 = 1;
let quantized_timestamp = (timestamp - self.config.lag_interval_seconds)
.checked_div(self.config.lag_interval_seconds)
Expand Down
34 changes: 16 additions & 18 deletions crates/apollo_l1_gas_price/src/exchange_rate_oracle_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,16 +60,14 @@ async fn eth_to_fri_rate_uses_cache_on_quantized_hit() {
let client = ExchangeRateOracleClient::new(config.clone());

// First request should fail because the cache is empty.
assert!(client.eth_to_fri_rate(TIMESTAMP1).await.is_err());
assert!(client.fetch_rate(TIMESTAMP1).await.is_err());
// Wait for the query to resolve.
while client.eth_to_fri_rate(TIMESTAMP1).await.is_err() {
while client.fetch_rate(TIMESTAMP1).await.is_err() {
tokio::task::yield_now().await; // Don't block the executor.
}
let rate1 = client.eth_to_fri_rate(TIMESTAMP1).await.unwrap();
let rate2 = client
.eth_to_fri_rate(TIMESTAMP2)
.await
.expect("Should resolve immediately due to the cache");
let rate1 = client.fetch_rate(TIMESTAMP1).await.unwrap();
let rate2 =
client.fetch_rate(TIMESTAMP2).await.expect("Should resolve immediately due to the cache");
assert_eq!(rate1, rate2);
}

Expand Down Expand Up @@ -134,28 +132,28 @@ async fn eth_to_fri_rate_uses_prev_cache_when_query_not_ready() {
let client = ExchangeRateOracleClient::new(config.clone());

// First request should fail because the cache is empty.
assert!(client.eth_to_fri_rate(TIMESTAMP1).await.is_err());
assert!(client.fetch_rate(TIMESTAMP1).await.is_err());
// Wait for the query to resolve.
while client.eth_to_fri_rate(TIMESTAMP1).await.is_err() {
while client.fetch_rate(TIMESTAMP1).await.is_err() {
tokio::task::yield_now().await; // Don't block the executor.
}
let rate1 = client.eth_to_fri_rate(TIMESTAMP1).await.unwrap();
let rate1 = client.fetch_rate(TIMESTAMP1).await.unwrap();
assert_eq!(rate1, EXPECTED_RATE);
// Second request should resolve immediately due to the cache.
let rate2 = client.eth_to_fri_rate(TIMESTAMP2).await.unwrap();
let rate2 = client.fetch_rate(TIMESTAMP2).await.unwrap();
assert_eq!(rate2, EXPECTED_RATE);

// Wait for the query to resolve, and the price to be updated.
for _ in 0..100 {
let current_rate = client.eth_to_fri_rate(TIMESTAMP2).await.unwrap();
let current_rate = client.fetch_rate(TIMESTAMP2).await.unwrap();
if current_rate > EXPECTED_RATE {
break;
}
tokio::time::sleep(Duration::from_millis(1)).await;
}

// Third request should already successfully get the query from the server.
let rate3 = client.eth_to_fri_rate(TIMESTAMP2).await.unwrap();
let rate3 = client.fetch_rate(TIMESTAMP2).await.unwrap();
assert_eq!(rate3, different_rate);
}

Expand Down Expand Up @@ -194,22 +192,22 @@ async fn eth_to_fri_rate_two_urls() {
};
let client = ExchangeRateOracleClient::new(config.clone());
// First request should fail because the cache is empty.
assert!(client.eth_to_fri_rate(TIMESTAMP1).await.is_err());
assert!(client.fetch_rate(TIMESTAMP1).await.is_err());
// Wait for the query to resolve.
while client.eth_to_fri_rate(TIMESTAMP1).await.is_err() {
while client.fetch_rate(TIMESTAMP1).await.is_err() {
tokio::task::yield_now().await; // Don't block the executor.
}
let rate1 = client.eth_to_fri_rate(TIMESTAMP1).await.unwrap();
let rate1 = client.fetch_rate(TIMESTAMP1).await.unwrap();
assert_eq!(rate1, EXPECTED_RATE);

// Note this server fails on missing "decimals", not "price".
let _mock_response3 =
make_server(&mut server2, json!({"price": &expected_rate_hex, "bar": 18})).await;
// First request should fail because the cache is empty.
assert!(client.eth_to_fri_rate(TIMESTAMP2).await.is_err());
assert!(client.fetch_rate(TIMESTAMP2).await.is_err());
// Wait for the query to resolve.
loop {
match client.eth_to_fri_rate(TIMESTAMP2).await {
match client.fetch_rate(TIMESTAMP2).await {
Ok(_) => panic!("Both servers should be returning bad JSON!"),
Err(ExchangeRateOracleClientError::QueryNotReadyError(_)) => {}
Err(ExchangeRateOracleClientError::AllUrlsFailedError(_, index)) => {
Expand Down
2 changes: 1 addition & 1 deletion crates/apollo_l1_gas_price/src/l1_gas_price_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ impl L1GasPriceProvider {

pub async fn eth_to_fri_rate(&self, timestamp: u64) -> L1GasPriceProviderResult<u128> {
self.eth_to_strk_oracle_client
.eth_to_fri_rate(timestamp)
.fetch_rate(timestamp)
.await
.map_err(L1GasPriceProviderError::ExchangeRateOracleClientError)
}
Expand Down
6 changes: 4 additions & 2 deletions crates/apollo_l1_gas_price_types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,8 +105,10 @@ pub trait L1GasPriceProviderClient: Send + Sync {
#[cfg_attr(any(feature = "testing", test), automock)]
#[async_trait]
pub trait ExchangeRateOracleClientTrait: Send + Sync + Debug {
/// Fetches the eth to fri rate for a given timestamp.
async fn eth_to_fri_rate(&self, timestamp: u64) -> Result<u128, ExchangeRateOracleClientError>;
/// Fetches a rate as a u128 for the given timestamp. The semantics of the rate (e.g.
/// ETH/FRI, STRK/USD) are determined by the URLs the implementation is configured with;
/// callers label the per-instance meaning at the field that holds the trait object.
async fn fetch_rate(&self, timestamp: u64) -> Result<u128, ExchangeRateOracleClientError>;
}

#[async_trait]
Expand Down
Loading