Skip to content

Commit

Permalink
feat(base-token): Base token price ratio cache update frequency confi…
Browse files Browse the repository at this point in the history
…gurable (#2388)

## What ❔

This PR makes base token price ration cache update frequency
configurable

## Why ❔

Base token price ratio is updated in DB with configurable frequency, but
when used it's taken from cache that is updated in non-configurable
manner

## Checklist

<!-- Check your PR fulfills the following items. -->
<!-- For draft PRs check the boxes as you complete them. -->

- [x] PR title corresponds to the body of PR (we generate changelog
entries from PRs).
- [x] Tests for the changes have been added / updated.
- [x] Documentation comments have been added / updated.
- [x] Code has been formatted via `zk fmt` and `zk lint`.
  • Loading branch information
cytadela8 authored Jul 9, 2024
1 parent 598ef7b commit fb4d700
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 12 deletions.
4 changes: 3 additions & 1 deletion core/bin/zksync_server/src/node_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,9 @@ impl MainNodeBuilder {
fn add_sequencer_l1_gas_layer(mut self) -> anyhow::Result<Self> {
// Ensure the BaseTokenRatioProviderResource is inserted if the base token is not ETH.
if self.contracts_config.base_token_addr != Some(SHARED_BRIDGE_ETHER_TOKEN_ADDRESS) {
self.node.add_layer(BaseTokenRatioProviderLayer {});
let base_token_adjuster_config = try_load_config!(self.configs.base_token_adjuster);
self.node
.add_layer(BaseTokenRatioProviderLayer::new(base_token_adjuster_config));
}

let gas_adjuster_config = try_load_config!(self.configs.eth)
Expand Down
24 changes: 20 additions & 4 deletions core/lib/config/src/configs/base_token_adjuster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,30 +2,46 @@ use std::time::Duration;

use serde::Deserialize;

/// By default the ratio persister will run every 30 seconds.
/// By default, the ratio persister will run every 30 seconds.
pub const DEFAULT_INTERVAL_MS: u64 = 30_000;

/// By default, refetch ratio from db every 0.5 second
pub const DEFAULT_CACHE_UPDATE_INTERVAL: u64 = 500;

#[derive(Debug, Clone, PartialEq, Deserialize)]
pub struct BaseTokenAdjusterConfig {
/// How often to spark a new cycle of the ratio persister to fetch external prices and persis ratios.
#[serde(default = "BaseTokenAdjusterConfig::default_interval")]
#[serde(default = "BaseTokenAdjusterConfig::default_polling_interval")]
pub price_polling_interval_ms: u64,

/// We (in memory) cache the ratio fetched from db. This interval defines frequency of refetch from db.
#[serde(default = "BaseTokenAdjusterConfig::default_cache_update_interval")]
pub price_cache_update_interval_ms: u64,
}

impl Default for BaseTokenAdjusterConfig {
fn default() -> Self {
Self {
price_polling_interval_ms: Self::default_interval(),
price_polling_interval_ms: Self::default_polling_interval(),
price_cache_update_interval_ms: Self::default_cache_update_interval(),
}
}
}

impl BaseTokenAdjusterConfig {
fn default_interval() -> u64 {
fn default_polling_interval() -> u64 {
DEFAULT_INTERVAL_MS
}

pub fn price_polling_interval(&self) -> Duration {
Duration::from_millis(self.price_polling_interval_ms)
}

fn default_cache_update_interval() -> u64 {
DEFAULT_CACHE_UPDATE_INTERVAL
}

pub fn price_cache_update_interval(&self) -> Duration {
Duration::from_millis(self.price_cache_update_interval_ms)
}
}
5 changes: 5 additions & 0 deletions core/lib/protobuf_config/src/base_token_adjuster.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,17 @@ impl ProtoRepr for proto::BaseTokenAdjuster {
price_polling_interval_ms: self
.price_polling_interval_ms
.expect("price_polling_interval_ms"),

price_cache_update_interval_ms: self
.price_cache_update_interval_ms
.expect("price_cache_update_interval_ms"),
})
}

fn build(this: &Self::Type) -> Self {
Self {
price_polling_interval_ms: Some(this.price_polling_interval_ms),
price_cache_update_interval_ms: Some(this.price_cache_update_interval_ms),
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ package zksync.config.base_token_adjuster;

message BaseTokenAdjuster {
optional uint64 price_polling_interval_ms = 1;
optional uint64 price_cache_update_interval_ms = 2;
}
13 changes: 8 additions & 5 deletions core/node/base_token_adjuster/src/base_token_ratio_provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,15 @@ use std::{
fmt::Debug,
num::NonZeroU64,
sync::{Arc, RwLock},
time::Duration,
};

use anyhow::Context;
use async_trait::async_trait;
use tokio::sync::watch;
use zksync_config::BaseTokenAdjusterConfig;
use zksync_dal::{ConnectionPool, Core, CoreDal};
use zksync_types::fee_model::BaseTokenConversionRatio;

const CACHE_UPDATE_INTERVAL: Duration = Duration::from_millis(500);

#[async_trait]
pub trait BaseTokenRatioProvider: Debug + Send + Sync + 'static {
fn get_conversion_ratio(&self) -> BaseTokenConversionRatio;
Expand All @@ -22,13 +20,18 @@ pub trait BaseTokenRatioProvider: Debug + Send + Sync + 'static {
pub struct DBBaseTokenRatioProvider {
pub pool: ConnectionPool<Core>,
pub latest_ratio: Arc<RwLock<BaseTokenConversionRatio>>,
config: BaseTokenAdjusterConfig,
}

impl DBBaseTokenRatioProvider {
pub async fn new(pool: ConnectionPool<Core>) -> anyhow::Result<Self> {
pub async fn new(
pool: ConnectionPool<Core>,
config: BaseTokenAdjusterConfig,
) -> anyhow::Result<Self> {
let fetcher = Self {
pool,
latest_ratio: Arc::default(),
config,
};
fetcher.update_latest_price().await?;

Expand All @@ -46,7 +49,7 @@ impl DBBaseTokenRatioProvider {
}

pub async fn run(&self, mut stop_receiver: watch::Receiver<bool>) -> anyhow::Result<()> {
let mut timer = tokio::time::interval(CACHE_UPDATE_INTERVAL);
let mut timer = tokio::time::interval(self.config.price_cache_update_interval());

while !*stop_receiver.borrow_and_update() {
tokio::select! {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::sync::Arc;

use zksync_base_token_adjuster::DBBaseTokenRatioProvider;
use zksync_config::BaseTokenAdjusterConfig;

use crate::{
implementations::resources::{
Expand All @@ -22,7 +23,15 @@ use crate::{
/// If the base token is ETH, a default, no-op impl of the BaseTokenRatioProviderResource is used by other
/// layers to always return a conversion ratio of 1.
#[derive(Debug)]
pub struct BaseTokenRatioProviderLayer;
pub struct BaseTokenRatioProviderLayer {
config: BaseTokenAdjusterConfig,
}

impl BaseTokenRatioProviderLayer {
pub fn new(config: BaseTokenAdjusterConfig) -> Self {
Self { config }
}
}

#[derive(Debug, FromContext)]
#[context(crate = crate)]
Expand Down Expand Up @@ -50,7 +59,7 @@ impl WiringLayer for BaseTokenRatioProviderLayer {
async fn wire(self, input: Self::Input) -> Result<Self::Output, WiringError> {
let replica_pool = input.replica_pool.get().await.unwrap();

let ratio_provider = DBBaseTokenRatioProvider::new(replica_pool).await?;
let ratio_provider = DBBaseTokenRatioProvider::new(replica_pool, self.config).await?;
// Cloning the provided preserves the internal state.
Ok(Output {
ratio_provider: Arc::new(ratio_provider.clone()).into(),
Expand Down
2 changes: 2 additions & 0 deletions etc/env/base/base_token_adjuster.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@

# How often to poll external price feeds for the base token price.
price_polling_interval_ms = "30000"

price_cache_update_interval_ms = "2000"
1 change: 1 addition & 0 deletions etc/env/file_based/general.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ prover_group:
aggregation_round: 1
base_token_adjuster:
price_polling_interval_ms: 30000
price_cache_update_interval_ms: 2000

house_keeper:
l1_batch_metrics_reporting_interval_ms: 10000
Expand Down

0 comments on commit fb4d700

Please sign in to comment.