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: different scaling gas constants based on forked network #295

Merged
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
97 changes: 80 additions & 17 deletions src/fork.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,12 @@ use zksync_web3_decl::{
};
use zksync_web3_decl::{namespaces::EthNamespaceClient, types::Index};

use crate::system_contracts;
use crate::{cache::CacheConfig, node::TEST_NODE_NETWORK_ID};
use crate::{deps::InMemoryStorage, http_fork_source::HttpForkSource};
use crate::{
node::{DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR, DEFAULT_ESTIMATE_GAS_SCALE_FACTOR},
system_contracts,
};

pub fn block_on<F: Future + Send + 'static>(future: F) -> F::Output
where
Expand All @@ -52,6 +55,40 @@ where
.unwrap()
}

/// The possible networks to fork from.
#[derive(Debug, Clone)]
pub enum ForkNetwork {
Mainnet,
SepoliaTestnet,
GoerliTestnet,
Other(String),
}

impl ForkNetwork {
/// Return the URL for the underlying fork source.
pub fn to_url(&self) -> &str {
match self {
ForkNetwork::Mainnet => "https://mainnet.era.zksync.io:443",
ForkNetwork::SepoliaTestnet => "https://sepolia.era.zksync.dev:443",
ForkNetwork::GoerliTestnet => "https://testnet.era.zksync.dev:443",
ForkNetwork::Other(url) => url,
}
}

/// Returns the local gas scale factors currently in use by the upstream network.
pub fn local_gas_scale_factors(&self) -> (f64, f32) {
match self {
ForkNetwork::Mainnet => (1.5, 1.2),
ForkNetwork::SepoliaTestnet => (2.0, 1.2),
ForkNetwork::GoerliTestnet => (1.2, 1.2),
ForkNetwork::Other(_) => (
DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR,
DEFAULT_ESTIMATE_GAS_SCALE_FACTOR,
),
}
}
}

/// In memory storage, that allows 'forking' from other network.
/// If forking is enabled, it reads missing data from remote location.
/// S - is a struct that is used for source of the fork.
Expand Down Expand Up @@ -321,6 +358,10 @@ pub struct ForkDetails<S> {
pub overwrite_chain_id: Option<L2ChainId>,
pub l1_gas_price: u64,
pub l2_fair_gas_price: u64,
/// L1 Gas Price Scale Factor for gas estimation.
pub estimate_gas_price_scale_factor: f64,
/// The factor by which to scale the gasLimit.
pub estimate_gas_scale_factor: f32,
}

const SUPPORTED_VERSIONS: &[ProtocolVersionId] = &[
Expand Down Expand Up @@ -356,13 +397,14 @@ pub fn supported_versions_to_string() -> String {
}

impl ForkDetails<HttpForkSource> {
pub async fn from_url_and_miniblock_and_chain(
url: &str,
pub async fn from_network_and_miniblock_and_chain(
network: ForkNetwork,
client: Client<L2>,
miniblock: u64,
chain_id: Option<L2ChainId>,
cache_config: CacheConfig,
) -> Self {
let url = network.to_url();
let block_details = client
.get_block_details(L2BlockNumber(miniblock as u32))
.await
Expand Down Expand Up @@ -402,6 +444,8 @@ impl ForkDetails<HttpForkSource> {
);
}

let (estimate_gas_price_scale_factor, estimate_gas_scale_factor) =
network.local_gas_scale_factors();
ForkDetails {
fork_source: HttpForkSource::new(url.to_owned(), cache_config),
l1_block: l1_batch_number,
Expand All @@ -412,23 +456,32 @@ impl ForkDetails<HttpForkSource> {
overwrite_chain_id: chain_id,
l1_gas_price: block_details.base.l1_gas_price,
l2_fair_gas_price: block_details.base.l2_fair_gas_price,
estimate_gas_price_scale_factor,
estimate_gas_scale_factor,
}
}
/// Create a fork from a given network at a given height.
pub async fn from_network(fork: &str, fork_at: Option<u64>, cache_config: CacheConfig) -> Self {
let (url, client) = Self::fork_to_url_and_client(fork);
let (network, client) = Self::fork_network_and_client(fork);
let l2_miniblock = if let Some(fork_at) = fork_at {
fork_at
} else {
client.get_block_number().await.unwrap().as_u64()
};
Self::from_url_and_miniblock_and_chain(url, client, l2_miniblock, None, cache_config).await
Self::from_network_and_miniblock_and_chain(
network,
client,
l2_miniblock,
None,
cache_config,
)
.await
}

/// Create a fork from a given network, at a height BEFORE a transaction.
/// This will allow us to apply this transaction locally on top of this fork.
pub async fn from_network_tx(fork: &str, tx: H256, cache_config: CacheConfig) -> Self {
let (url, client) = Self::fork_to_url_and_client(fork);
let (network, client) = Self::fork_network_and_client(fork);
let tx_details = client.get_transaction_by_hash(tx).await.unwrap().unwrap();
let overwrite_chain_id = Some(
L2ChainId::try_from(tx_details.chain_id.as_u64()).unwrap_or_else(|err| {
Expand All @@ -439,8 +492,8 @@ impl ForkDetails<HttpForkSource> {
// We have to sync to the one-miniblock before the one where transaction is.
let l2_miniblock = miniblock_number.saturating_sub(1) as u64;

Self::from_url_and_miniblock_and_chain(
url,
Self::from_network_and_miniblock_and_chain(
network,
client,
l2_miniblock,
overwrite_chain_id,
Expand All @@ -451,22 +504,23 @@ impl ForkDetails<HttpForkSource> {
}

impl<S: ForkSource> ForkDetails<S> {
/// Return URL and HTTP client for a given fork name.
pub fn fork_to_url_and_client(fork: &str) -> (&str, Client<L2>) {
let url = match fork {
"mainnet" => "https://mainnet.era.zksync.io:443",
"sepolia-testnet" => "https://sepolia.era.zksync.dev:443",
"goerli-testnet" => "https://testnet.era.zksync.dev:443",
_ => fork,
/// Return [`ForkNetwork`] and HTTP client for a given fork name.
pub fn fork_network_and_client(fork: &str) -> (ForkNetwork, Client<L2>) {
let network = match fork {
"mainnet" => ForkNetwork::Mainnet,
"sepolia-testnet" => ForkNetwork::SepoliaTestnet,
"goerli-testnet" => ForkNetwork::GoerliTestnet,
_ => ForkNetwork::Other(fork.to_string()),
};

let url = network.to_url();
let parsed_url = SensitiveUrl::from_str(url)
.unwrap_or_else(|_| panic!("Unable to parse client URL: {}", &url));
let client = Client::http(parsed_url)
.unwrap_or_else(|_| panic!("Unable to create a client for fork: {}", &url))
.build();

(url, client)
(network, client)
}

/// Returns transactions that are in the same L2 miniblock as replay_tx, but were executed before it.
Expand Down Expand Up @@ -508,7 +562,14 @@ mod tests {
use zksync_state::ReadStorage;
use zksync_types::{api::TransactionVariant, StorageKey};

use crate::{deps::InMemoryStorage, node::DEFAULT_L2_GAS_PRICE, system_contracts, testing};
use crate::{
deps::InMemoryStorage,
node::{
DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR, DEFAULT_ESTIMATE_GAS_SCALE_FACTOR,
DEFAULT_L2_GAS_PRICE,
},
system_contracts, testing,
};

use super::{ForkDetails, ForkStorage};

Expand Down Expand Up @@ -538,6 +599,8 @@ mod tests {
overwrite_chain_id: None,
l1_gas_price: 100,
l2_fair_gas_price: DEFAULT_L2_GAS_PRICE,
estimate_gas_price_scale_factor: DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR,
estimate_gas_scale_factor: DEFAULT_ESTIMATE_GAS_SCALE_FACTOR,
};

let mut fork_storage = ForkStorage::new(Some(fork_details), &options);
Expand Down
13 changes: 12 additions & 1 deletion src/node/fee_model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,24 @@ use zksync_types::L1_GAS_PER_PUBDATA_BYTE;
pub struct TestNodeFeeInputProvider {
pub l1_gas_price: u64,
pub l2_gas_price: u64,
/// L1 Gas Price Scale Factor for gas estimation.
pub estimate_gas_price_scale_factor: f64,
/// The factor by which to scale the gasLimit.
pub estimate_gas_scale_factor: f32,
}

impl TestNodeFeeInputProvider {
pub fn new(l1_gas_price: u64, l2_gas_price: u64) -> Self {
pub fn new(
l1_gas_price: u64,
l2_gas_price: u64,
estimate_gas_price_scale_factor: f64,
estimate_gas_scale_factor: f32,
) -> Self {
Self {
l1_gas_price,
l2_gas_price,
estimate_gas_price_scale_factor,
estimate_gas_scale_factor,
}
}

Expand Down
24 changes: 17 additions & 7 deletions src/node/in_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,11 @@ pub const L1_GAS_PRICE: u64 = 50_000_000_000;
/// The default L2 Gas Price to be used if not supplied via the CLI argument.
pub const DEFAULT_L2_GAS_PRICE: u64 = 25_000_000;
/// L1 Gas Price Scale Factor for gas estimation.
pub const ESTIMATE_GAS_PRICE_SCALE_FACTOR: f64 = 1.5;
pub const DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR: f64 = 1.5;
/// Acceptable gas overestimation limit.
pub const ESTIMATE_GAS_ACCEPTABLE_OVERESTIMATION: u64 = 1_000;
/// The factor by which to scale the gasLimit.
pub const ESTIMATE_GAS_SCALE_FACTOR: f32 = 1.3;
pub const DEFAULT_ESTIMATE_GAS_SCALE_FACTOR: f32 = 1.3;
/// The maximum number of previous blocks to store the state for.
pub const MAX_PREVIOUS_STATES: u16 = 128;
/// The zks protocol version.
Expand Down Expand Up @@ -455,8 +455,8 @@ impl<S: std::fmt::Debug + ForkSource> InMemoryNodeInner<S> {
let fee_input = block_on(async move {
fee_input_provider
.get_batch_fee_input_scaled(
ESTIMATE_GAS_PRICE_SCALE_FACTOR,
ESTIMATE_GAS_PRICE_SCALE_FACTOR,
fee_input_provider.estimate_gas_price_scale_factor,
fee_input_provider.estimate_gas_price_scale_factor,
)
.await
.unwrap()
Expand Down Expand Up @@ -584,11 +584,15 @@ impl<S: std::fmt::Debug + ForkSource> InMemoryNodeInner<S> {

tracing::trace!("Gas Estimation Values:");
tracing::trace!(" Final upper_bound: {}", upper_bound);
tracing::trace!(" ESTIMATE_GAS_SCALE_FACTOR: {}", ESTIMATE_GAS_SCALE_FACTOR);
tracing::trace!(
" ESTIMATE_GAS_SCALE_FACTOR: {}",
self.fee_input_provider.estimate_gas_scale_factor
);
tracing::trace!(" MAX_L2_TX_GAS_LIMIT: {}", MAX_L2_TX_GAS_LIMIT);
let tx_body_gas_limit = upper_bound;
let suggested_gas_limit =
((upper_bound + additional_gas_for_pubdata) as f32 * ESTIMATE_GAS_SCALE_FACTOR) as u64;
let suggested_gas_limit = ((upper_bound + additional_gas_for_pubdata) as f32
* self.fee_input_provider.estimate_gas_scale_factor)
as u64;

let estimate_gas_result = InMemoryNodeInner::estimate_gas_step(
l2_tx.clone(),
Expand Down Expand Up @@ -953,6 +957,8 @@ impl<S: ForkSource + std::fmt::Debug + Clone> InMemoryNode<S> {
fee_input_provider: TestNodeFeeInputProvider::new(
f.l1_gas_price,
config.l2_fair_gas_price,
f.estimate_gas_price_scale_factor,
f.estimate_gas_scale_factor,
),
tx_results: Default::default(),
blocks,
Expand Down Expand Up @@ -990,6 +996,8 @@ impl<S: ForkSource + std::fmt::Debug + Clone> InMemoryNode<S> {
fee_input_provider: TestNodeFeeInputProvider::new(
L1_GAS_PRICE,
config.l2_fair_gas_price,
DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR,
DEFAULT_ESTIMATE_GAS_SCALE_FACTOR,
),
tx_results: Default::default(),
blocks,
Expand Down Expand Up @@ -1888,6 +1896,8 @@ mod tests {
overwrite_chain_id: None,
l1_gas_price: 1000,
l2_fair_gas_price: DEFAULT_L2_GAS_PRICE,
estimate_gas_price_scale_factor: DEFAULT_ESTIMATE_GAS_PRICE_SCALE_FACTOR,
estimate_gas_scale_factor: DEFAULT_ESTIMATE_GAS_SCALE_FACTOR,
}),
None,
Default::default(),
Expand Down
Loading