Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(base-token): Base token price ratio cache update frequency configurable #2388

Merged
merged 7 commits into from
Jul 9, 2024
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
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 @@ -297,6 +297,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
Loading