Skip to content

Commit a8e5952

Browse files
authored
feat(eth_sender): Properly calculate blob price (#4406)
## What ❔ <!-- What are the changes this PR brings about? --> <!-- Example: This PR adds a PR template to the repo. --> <!-- (For bigger PRs adding more context is appreciated) --> ## Why ❔ <!-- Why are these changes done? What goal do they contribute to? What are the principles behind them? --> <!-- The `Why` has to be clear to non-Matter Labs entities running their own ZK Chain --> <!-- Example: PR templates ensure PR reviewers, observers, and future iterators are in context about the evolution of repos. --> ## Is this a breaking change? - [ ] Yes - [ ] No ## Operational changes <!-- Any config changes? Any new flags? Any changes to any scripts? --> <!-- Please add anything that non-Matter Labs entities running their own ZK Chain may need to know --> ## Checklist <!-- Check your PR fulfills the following items. --> <!-- For draft PRs check the boxes as you complete them. --> - [ ] PR title corresponds to the body of PR (we generate changelog entries from PRs). - [ ] Tests for the changes have been added / updated. - [ ] Documentation comments have been added / updated. - [ ] Code has been formatted via `zkstack dev fmt` and `zkstack dev lint`.
1 parent bfda346 commit a8e5952

28 files changed

+460
-27
lines changed

core/Cargo.lock

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/lib/dal/.sqlx/query-3db31982ac100a2b2de24f8a42b9f5882d69055a3399f046adea196ae053d6a3.json

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/lib/dal/.sqlx/query-a0ad14cd53afb6c360e70c47dbd79d66dd9fbd20941aec20e2e8c3874b15a953.json renamed to core/lib/dal/.sqlx/query-9e9b1ff2089d168b1b0819bd6fc3fb70c38712f13c80c5b474d8d2227958fb74.json

Lines changed: 4 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/lib/dal/.sqlx/query-fb416f211acb48e62c17df756ce349d7eebea1ad46df430376aac84fd67a88f1.json

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE l1_batches DROP COLUMN blobs_amount;
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ALTER TABLE l1_batches ADD COLUMN blobs_amount BIGINT DEFAULT 0;

core/lib/dal/src/blocks_dal.rs

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use std::{
66
};
77

88
use anyhow::Context as _;
9-
use bigdecimal::{BigDecimal, FromPrimitive};
9+
use bigdecimal::{BigDecimal, FromPrimitive, ToPrimitive};
1010
use sqlx::types::chrono::{DateTime, Utc};
1111
use zksync_db_connection::{
1212
connection::Connection,
@@ -1116,6 +1116,7 @@ impl BlocksDal<'_, '_> {
11161116
storage_refunds: &[u32],
11171117
pubdata_costs: &[i32],
11181118
predicted_circuits_by_type: CircuitStatistic, // predicted number of circuits for each circuit type
1119+
bytes_per_blob: u64,
11191120
) -> anyhow::Result<()> {
11201121
let initial_bootloader_contents_len = initial_bootloader_contents.len();
11211122
let instrumentation = Instrumented::new("mark_l1_batch_as_sealed")
@@ -1143,6 +1144,12 @@ impl BlocksDal<'_, '_> {
11431144
let storage_refunds: Vec<_> = storage_refunds.iter().copied().map(i64::from).collect();
11441145
let pubdata_costs: Vec<_> = pubdata_costs.iter().copied().map(i64::from).collect();
11451146

1147+
let blobs_amount = pubdata_input
1148+
.clone()
1149+
.map(|input| input.len() as u64)
1150+
.unwrap_or(0)
1151+
.div_ceil(bytes_per_blob);
1152+
11461153
let query = sqlx::query!(
11471154
r#"
11481155
UPDATE l1_batches
@@ -1163,6 +1170,7 @@ impl BlocksDal<'_, '_> {
11631170
pubdata_costs = $15,
11641171
pubdata_input = $16,
11651172
predicted_circuits_by_type = $17,
1173+
blobs_amount = $18,
11661174
updated_at = NOW(),
11671175
sealed_at = NOW(),
11681176
is_sealed = TRUE
@@ -1190,6 +1198,7 @@ impl BlocksDal<'_, '_> {
11901198
&pubdata_costs,
11911199
pubdata_input,
11921200
serde_json::to_value(predicted_circuits_by_type).unwrap(),
1201+
blobs_amount as i64,
11931202
);
11941203
let update_result = instrumentation.with(query).execute(self.storage).await?;
11951204

@@ -1203,6 +1212,29 @@ impl BlocksDal<'_, '_> {
12031212
Ok(())
12041213
}
12051214

1215+
pub async fn get_blobs_amount_for_range(
1216+
&mut self,
1217+
lower_bound: L1BatchNumber,
1218+
upper_bound: L1BatchNumber,
1219+
) -> DalResult<u64> {
1220+
let result: u64 = sqlx::query!(
1221+
r#"
1222+
SELECT SUM(blobs_amount) FROM l1_batches WHERE number BETWEEN $1 AND $2
1223+
"#,
1224+
i64::from(lower_bound.0),
1225+
i64::from(upper_bound.0)
1226+
)
1227+
.instrument("get_blobs_amount_for_range")
1228+
.fetch_optional(self.storage)
1229+
.await?
1230+
.map(|r| r.sum)
1231+
.unwrap()
1232+
.map(|x| x.to_i64().unwrap() as u64)
1233+
.unwrap_or(0);
1234+
1235+
Ok(result)
1236+
}
1237+
12061238
pub async fn get_unsealed_l1_batch(&mut self) -> DalResult<Option<UnsealedL1BatchHeader>> {
12071239
Self::get_unsealed_l1_batch_inner(self.storage).await
12081240
}
@@ -3584,7 +3616,7 @@ impl BlocksDal<'_, '_> {
35843616

35853617
pub async fn insert_mock_l1_batch(&mut self, header: &L1BatchHeader) -> anyhow::Result<()> {
35863618
self.insert_l1_batch(header.to_unsealed_header()).await?;
3587-
self.mark_l1_batch_as_sealed(header, &[], &[], &[], Default::default())
3619+
self.mark_l1_batch_as_sealed(header, &[], &[], &[], Default::default(), 1)
35883620
.await
35893621
}
35903622

core/lib/dal/src/eth_sender_dal.rs

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,13 @@ use zksync_types::{
1010
AggregatedActionType, L1BatchAggregatedActionType, L2BlockAggregatedActionType,
1111
},
1212
eth_sender::{EthTx, EthTxBlobSidecar, EthTxFinalityStatus, TxHistory},
13+
server_notification::GatewayMigrationNotification,
1314
Address, L1BatchNumber, L2BlockNumber, SLChainId, H256, U256,
1415
};
1516

1617
use crate::{
1718
models::storage_eth_tx::{BlocksEthSenderStats, StorageEthTx, StorageTxHistory},
18-
Core,
19+
Core, CoreDal,
1920
};
2021

2122
#[derive(Debug)]
@@ -291,6 +292,72 @@ impl EthSenderDal<'_, '_> {
291292
Ok(stats)
292293
}
293294

295+
/// This query returns the number and sent_at_block of the latest commited batch.
296+
/// Query should be primary used for L1, not for gateway settlement layer.
297+
pub async fn get_number_and_sent_at_block_for_latest_commited_batch(
298+
&mut self,
299+
latest_block_number: u32,
300+
) -> DalResult<(u32, u32)> {
301+
// if no commited batch found, return first batch number and latest block number
302+
let result = sqlx::query!(
303+
r#"
304+
SELECT number, eth_txs_history.sent_at_block, eth_txs.is_gateway
305+
FROM l1_batches
306+
INNER JOIN
307+
eth_txs_history
308+
ON l1_batches.eth_commit_tx_id = eth_txs_history.eth_tx_id
309+
INNER JOIN eth_txs ON eth_txs_history.eth_tx_id = eth_txs.id
310+
WHERE eth_txs_history.finality_status = 'finalized'
311+
ORDER BY number DESC
312+
LIMIT 1
313+
"#,
314+
)
315+
.instrument("get_number_and_sent_at_block_for_latest_commited_batch")
316+
.fetch_optional(self.storage)
317+
.await?;
318+
319+
// Here we are returning final values based on the following logic:
320+
// - If there is no commited batch, we are returning 1 and latest block number
321+
// - If the commited batch is not a gateway batch, we are returning the batch number and the sent at block
322+
// - If the commited batch was a gateway batch, we are checking, if there was a gateway migration GW -> L1,
323+
// if so, we are returning the block number of the gateway migration, otherwise we are returning the latest block number
324+
match result {
325+
Some(row) => {
326+
let batch_number = row.number as u32;
327+
let sent_at_block = if !row.is_gateway {
328+
let block = row.sent_at_block.map(|v| v as u32);
329+
330+
if let Some(block) = block {
331+
block
332+
} else {
333+
tracing::error!("There is a commited batch, but no sent at block");
334+
latest_block_number
335+
}
336+
} else {
337+
let latest_notification = self
338+
.storage
339+
.server_notifications_dal()
340+
.get_latest_gateway_migration_notification_and_block_number()
341+
.await?;
342+
343+
if let Some((
344+
GatewayMigrationNotification::FromGateway,
345+
notification_block_number,
346+
)) = latest_notification
347+
{
348+
notification_block_number.0
349+
} else {
350+
tracing::error!("No latest GW -> L1 migration notification, but trying to calculate blob prices");
351+
latest_block_number
352+
}
353+
};
354+
355+
Ok((batch_number, sent_at_block))
356+
}
357+
None => Ok((1, latest_block_number)),
358+
}
359+
}
360+
294361
pub async fn get_eth_tx(&mut self, eth_tx_id: u32) -> sqlx::Result<Option<EthTx>> {
295362
Ok(sqlx::query_as!(
296363
StorageEthTx,

core/lib/dal/src/server_notifications.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,24 @@ impl ServerNotificationsDal<'_, '_> {
8383

8484
Ok(notification)
8585
}
86+
87+
pub async fn get_latest_gateway_migration_notification_and_block_number(
88+
&mut self,
89+
) -> DalResult<Option<(GatewayMigrationNotification, L1BlockNumber)>> {
90+
let notification = self
91+
.get_last_notification_by_topics(
92+
&GatewayMigrationNotification::get_server_notifier_topics(),
93+
)
94+
.await?;
95+
96+
let notification = notification.map(|notification| {
97+
(
98+
GatewayMigrationNotification::from_topic(notification.main_topic)
99+
.expect("Invalid topic"),
100+
notification.l1_block_number,
101+
)
102+
});
103+
104+
Ok(notification)
105+
}
86106
}

core/lib/dal/src/sync_dal.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -271,7 +271,7 @@ mod tests {
271271
.await
272272
.unwrap();
273273
conn.blocks_dal()
274-
.mark_l1_batch_as_sealed(&l1_batch_header, &[], &[], &[], Default::default())
274+
.mark_l1_batch_as_sealed(&l1_batch_header, &[], &[], &[], Default::default(), 1)
275275
.await
276276
.unwrap();
277277
conn.blocks_dal()

0 commit comments

Comments
 (0)