Skip to content

Commit

Permalink
feat(api): Add new l1_committed block tag (#2282)
Browse files Browse the repository at this point in the history
## Follow-ups: 
- add `l1_committed` tag to zksync-ethers codebase.
- update docs.

## What ❔
- added the new tag `L1Committed` to `BlockNumber` enum.
- added a new query to db to fetch l2 block, that was included into
committed on L1 `l1_batch` inside `resolve_block_id ` dal method.
- added unit test to check new feature `resolving_l1_committed_block_id
`.
- updated integration test.
- refactored `dal`'s tests - created `create_l1_batch_header` for tests
to avoid duplication.

## Why ❔

Chainlink needs this feature.

## 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`.
- [x] Spellcheck has been run via `zk spellcheck`.
  • Loading branch information
AnastasiiaVashchuk authored Jun 20, 2024
1 parent 0a38891 commit d5e8e9b
Show file tree
Hide file tree
Showing 10 changed files with 151 additions and 40 deletions.
11 changes: 9 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 2 additions & 10 deletions core/lib/dal/src/blocks_dal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2366,7 +2366,7 @@ mod tests {
};

use super::*;
use crate::{ConnectionPool, Core, CoreDal};
use crate::{tests::create_l1_batch_header, ConnectionPool, Core, CoreDal};

async fn save_mock_eth_tx(action_type: AggregatedActionType, conn: &mut Connection<'_, Core>) {
conn.eth_sender_dal()
Expand All @@ -2376,15 +2376,7 @@ mod tests {
}

fn mock_l1_batch_header() -> L1BatchHeader {
let mut header = L1BatchHeader::new(
L1BatchNumber(1),
100,
BaseSystemContractsHashes {
bootloader: H256::repeat_byte(1),
default_aa: H256::repeat_byte(42),
},
ProtocolVersionId::latest(),
);
let mut header = create_l1_batch_header(1);
header.l1_tx_count = 3;
header.l2_tx_count = 5;
header.l2_to_l1_logs.push(UserL2ToL1Log(L2ToL1Log {
Expand Down
96 changes: 94 additions & 2 deletions core/lib/dal/src/blocks_web3_dal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,24 @@ impl BlocksWeb3Dal<'_, '_> {
api::BlockId::Number(api::BlockNumber::Latest | api::BlockNumber::Committed) => (
"SELECT MAX(number) AS number FROM miniblocks";
),
api::BlockId::Number(api::BlockNumber::L1Committed) => (
"
SELECT COALESCE(
(
SELECT MAX(number) FROM miniblocks
WHERE l1_batch_number = (
SELECT number FROM l1_batches
JOIN eth_txs ON
l1_batches.eth_commit_tx_id = eth_txs.id
WHERE
eth_txs.confirmed_eth_tx_history_id IS NOT NULL
ORDER BY number DESC LIMIT 1
)
),
0
) AS number
";
),
api::BlockId::Number(api::BlockNumber::Finalized) => (
"
SELECT COALESCE(
Expand Down Expand Up @@ -733,6 +751,7 @@ impl BlocksWeb3Dal<'_, '_> {
#[cfg(test)]
mod tests {
use zksync_types::{
aggregated_operations::AggregatedActionType,
block::{L2BlockHasher, L2BlockHeader},
fee::TransactionExecutionMetrics,
Address, L2BlockNumber, ProtocolVersion, ProtocolVersionId,
Expand All @@ -741,8 +760,8 @@ mod tests {
use super::*;
use crate::{
tests::{
create_l2_block_header, create_snapshot_recovery, mock_execution_result,
mock_l2_transaction,
create_l1_batch_header, create_l2_block_header, create_snapshot_recovery,
mock_execution_result, mock_l2_transaction,
},
ConnectionPool, Core, CoreDal,
};
Expand Down Expand Up @@ -902,6 +921,79 @@ mod tests {
assert_eq!(l2_block_number, Some(L2BlockNumber(43)));
}

#[tokio::test]
async fn resolving_l1_committed_block_id() {
let connection_pool = ConnectionPool::<Core>::test_pool().await;
let mut conn = connection_pool.connection().await.unwrap();
conn.protocol_versions_dal()
.save_protocol_version_with_tx(&ProtocolVersion::default())
.await
.unwrap();

let l2_block_header = create_l2_block_header(1);
conn.blocks_dal()
.insert_l2_block(&l2_block_header)
.await
.unwrap();

let l1_batch_header = create_l1_batch_header(0);

conn.blocks_dal()
.insert_mock_l1_batch(&l1_batch_header)
.await
.unwrap();
conn.blocks_dal()
.mark_l2_blocks_as_executed_in_l1_batch(l1_batch_header.number)
.await
.unwrap();

let resolved_l2_block_number = conn
.blocks_web3_dal()
.resolve_block_id(api::BlockId::Number(api::BlockNumber::L1Committed))
.await
.unwrap();
assert_eq!(resolved_l2_block_number, Some(L2BlockNumber(0)));

let mocked_commit_eth_tx = conn
.eth_sender_dal()
.save_eth_tx(
0,
vec![],
AggregatedActionType::Commit,
Address::default(),
0,
None,
None,
)
.await
.unwrap();
let tx_hash = H256::random();
conn.eth_sender_dal()
.insert_tx_history(mocked_commit_eth_tx.id, 0, 0, None, tx_hash, &[], 0)
.await
.unwrap();
conn.eth_sender_dal()
.confirm_tx(tx_hash, U256::zero())
.await
.unwrap();
conn.blocks_dal()
.set_eth_tx_id(
l1_batch_header.number..=l1_batch_header.number,
mocked_commit_eth_tx.id,
AggregatedActionType::Commit,
)
.await
.unwrap();

let resolved_l2_block_number = conn
.blocks_web3_dal()
.resolve_block_id(api::BlockId::Number(api::BlockNumber::L1Committed))
.await
.unwrap();

assert_eq!(resolved_l2_block_number, Some(l2_block_header.number));
}

#[tokio::test]
async fn resolving_block_by_hash() {
let connection_pool = ConnectionPool::<Core>::test_pool().await;
Expand Down
15 changes: 3 additions & 12 deletions core/lib/dal/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,10 @@ pub async fn wait_for_l1_batch(

#[cfg(test)]
mod tests {
use zksync_contracts::BaseSystemContractsHashes;
use zksync_types::{block::L1BatchHeader, ProtocolVersion, ProtocolVersionId, H256};
use zksync_types::ProtocolVersion;

use super::*;
use crate::{ConnectionPool, Core, CoreDal};
use crate::{tests::create_l1_batch_header, ConnectionPool, Core, CoreDal};

#[tokio::test]
async fn waiting_for_l1_batch_success() {
Expand All @@ -59,15 +58,7 @@ mod tests {
.save_protocol_version_with_tx(&ProtocolVersion::default())
.await
.unwrap();
let header = L1BatchHeader::new(
L1BatchNumber(0),
100,
BaseSystemContractsHashes {
bootloader: H256::repeat_byte(1),
default_aa: H256::repeat_byte(42),
},
ProtocolVersionId::latest(),
);
let header = create_l1_batch_header(0);
conn.blocks_dal()
.insert_mock_l1_batch(&header)
.await
Expand Down
16 changes: 3 additions & 13 deletions core/lib/dal/src/pruning_dal/tests.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use std::ops;

use zksync_contracts::BaseSystemContractsHashes;
use zksync_db_connection::connection::Connection;
use zksync_types::{
block::L1BatchHeader,
fee::TransactionExecutionMetrics,
l2_to_l1_log::{L2ToL1Log, UserL2ToL1Log},
tx::IncludedTxLocation,
Expand All @@ -15,8 +13,8 @@ use super::*;
use crate::{
storage_logs_dal::DbStorageLog,
tests::{
create_l2_block_header, mock_execution_result, mock_l2_to_l1_log, mock_l2_transaction,
mock_vm_event,
create_l1_batch_header, create_l2_block_header, mock_execution_result, mock_l2_to_l1_log,
mock_l2_transaction, mock_vm_event,
},
ConnectionPool, Core, CoreDal,
};
Expand Down Expand Up @@ -89,15 +87,7 @@ async fn insert_events(conn: &mut Connection<'_, Core>, l2_block_number: L2Block
}

async fn insert_l1_batch(conn: &mut Connection<'_, Core>, l1_batch_number: L1BatchNumber) {
let mut header = L1BatchHeader::new(
l1_batch_number,
100,
BaseSystemContractsHashes {
bootloader: H256::repeat_byte(1),
default_aa: H256::repeat_byte(42),
},
ProtocolVersionId::latest(),
);
let mut header = create_l1_batch_header(*l1_batch_number);
header.l1_tx_count = 3;
header.l2_tx_count = 5;
header.l2_to_l1_logs.push(UserL2ToL1Log(L2ToL1Log {
Expand Down
13 changes: 12 additions & 1 deletion core/lib/dal/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::time::Duration;
use zksync_contracts::BaseSystemContractsHashes;
use zksync_db_connection::connection_pool::ConnectionPool;
use zksync_types::{
block::{L2BlockHasher, L2BlockHeader},
block::{L1BatchHeader, L2BlockHasher, L2BlockHeader},
fee::{Fee, TransactionExecutionMetrics},
fee_model::BatchFeeInput,
helpers::unix_timestamp_ms,
Expand Down Expand Up @@ -50,6 +50,17 @@ pub(crate) fn create_l2_block_header(number: u32) -> L2BlockHeader {
gas_limit: 0,
}
}
pub(crate) fn create_l1_batch_header(number: u32) -> L1BatchHeader {
L1BatchHeader::new(
L1BatchNumber(number),
100,
BaseSystemContractsHashes {
bootloader: H256::repeat_byte(1),
default_aa: H256::repeat_byte(42),
},
ProtocolVersionId::latest(),
)
}

pub(crate) fn mock_l2_transaction() -> L2Tx {
let fee = Fee {
Expand Down
4 changes: 4 additions & 0 deletions core/lib/types/src/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ pub enum BlockNumber {
Finalized,
/// Latest sealed block
Latest,
/// Last block that was committed on L1
L1Committed,
/// Earliest block (genesis)
Earliest,
/// Latest block (may be the block that is currently open).
Expand All @@ -51,6 +53,7 @@ impl Serialize for BlockNumber {
BlockNumber::Committed => serializer.serialize_str("committed"),
BlockNumber::Finalized => serializer.serialize_str("finalized"),
BlockNumber::Latest => serializer.serialize_str("latest"),
BlockNumber::L1Committed => serializer.serialize_str("l1_committed"),
BlockNumber::Earliest => serializer.serialize_str("earliest"),
BlockNumber::Pending => serializer.serialize_str("pending"),
}
Expand All @@ -73,6 +76,7 @@ impl<'de> Deserialize<'de> for BlockNumber {
"committed" => BlockNumber::Committed,
"finalized" => BlockNumber::Finalized,
"latest" => BlockNumber::Latest,
"l1_committed" => BlockNumber::L1Committed,
"earliest" => BlockNumber::Earliest,
"pending" => BlockNumber::Pending,
num => {
Expand Down
2 changes: 2 additions & 0 deletions core/node/api_server/src/web3/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ enum BlockIdLabel {
Committed,
Finalized,
Latest,
L1Committed,
Earliest,
Pending,
Number,
Expand Down Expand Up @@ -139,6 +140,7 @@ impl From<&MethodMetadata> for MethodLabels {
api::BlockId::Number(api::BlockNumber::Committed) => BlockIdLabel::Committed,
api::BlockId::Number(api::BlockNumber::Finalized) => BlockIdLabel::Finalized,
api::BlockId::Number(api::BlockNumber::Latest) => BlockIdLabel::Latest,
api::BlockId::Number(api::BlockNumber::L1Committed) => BlockIdLabel::L1Committed,
api::BlockId::Number(api::BlockNumber::Earliest) => BlockIdLabel::Earliest,
api::BlockId::Number(api::BlockNumber::Pending) => BlockIdLabel::Pending,
});
Expand Down
2 changes: 2 additions & 0 deletions core/tests/ts-integration/tests/api/web3.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -690,6 +690,8 @@ describe('web3 API compatibility tests', () => {
expect(+finalizedBlock.number!).toEqual(expect.any(Number));
const latestBlock = await alice.provider.send('eth_getBlockByNumber', ['latest', true]);
expect(+latestBlock.number!).toEqual(expect.any(Number));
const l1CommittedBlock = await alice.provider.send('eth_getBlockByNumber', ['l1_committed', true]);
expect(+l1CommittedBlock.number!).toEqual(expect.any(Number));
const pendingBlock = await alice.provider.send('eth_getBlockByNumber', ['pending', true]);
expect(pendingBlock).toEqual(null);
});
Expand Down

0 comments on commit d5e8e9b

Please sign in to comment.