diff --git a/core/lib/dal/src/consensus_dal.rs b/core/lib/dal/src/consensus_dal.rs index 8ec2d9584ac4..337e46fd734e 100644 --- a/core/lib/dal/src/consensus_dal.rs +++ b/core/lib/dal/src/consensus_dal.rs @@ -7,7 +7,7 @@ use zksync_db_connection::{ error::{DalError, DalResult, SqlxContext}, instrument::{InstrumentExt, Instrumented}, }; -use zksync_types::{L1BatchNumber, L2BlockNumber}; +use zksync_types::L2BlockNumber; pub use crate::consensus::Payload; use crate::{Core, CoreDal}; @@ -409,29 +409,12 @@ impl ConsensusDal<'_, '_> { /// /// Insertion is allowed even if it creates gaps in the L1 batch history. /// - /// It fails if the batch payload is missing or it's not consistent with the QC. + /// This method assumes that all payload validation has been carried out by the caller. pub async fn insert_batch_certificate( &mut self, cert: &attester::BatchQC, ) -> Result<(), InsertCertificateError> { - use InsertCertificateError as E; - let mut txn = self.storage.start_transaction().await?; - - let l1_batch_number = L1BatchNumber(cert.message.number.0 as u32); - let _l1_batch_header = txn - .blocks_dal() - .get_l1_batch_header(l1_batch_number) - .await? - .ok_or(E::MissingPayload)?; - - // TODO: Verify that the certificate matches the stored batch: - // * add the hash of the batch to the `BatchQC` - // * find out which field in the `l1_batches` table contains the hash we need to match - // * ideally move the responsibility of validation outside this method - - // if header.payload != want_payload.encode().hash() { - // return Err(E::PayloadMismatch); - // } + let l1_batch_number = cert.message.number.0 as i64; let res = sqlx::query!( r#" @@ -441,20 +424,18 @@ impl ConsensusDal<'_, '_> { ($1, $2, NOW(), NOW()) ON CONFLICT (l1_batch_number) DO NOTHING "#, - i64::from(l1_batch_number.0), + l1_batch_number, zksync_protobuf::serde::serialize(cert, serde_json::value::Serializer).unwrap(), ) .instrument("insert_batch_certificate") .report_latency() - .execute(&mut txn) + .execute(self.storage) .await?; if res.rows_affected().is_zero() { - tracing::debug!(%l1_batch_number, "duplicate batch certificate"); + tracing::debug!(l1_batch_number, "duplicate batch certificate"); } - txn.commit().await.context("commit")?; - Ok(()) } diff --git a/core/node/consensus/src/storage/connection.rs b/core/node/consensus/src/storage/connection.rs index e10f7a824918..d0d68aa12076 100644 --- a/core/node/consensus/src/storage/connection.rs +++ b/core/node/consensus/src/storage/connection.rs @@ -3,6 +3,7 @@ use zksync_concurrency::{ctx, error::Wrap as _, time}; use zksync_consensus_roles::{attester, validator}; use zksync_consensus_storage::{self as storage, BatchStoreState}; use zksync_dal::{consensus_dal::Payload, Core, CoreDal, DalError}; +use zksync_l1_contract_interface::i_executor::structures::StoredBatchInfo; use zksync_node_sync::{fetcher::IoCursorExt as _, ActionQueueSender, SyncState}; use zksync_state_keeper::io::common::IoCursor; use zksync_types::{commitment::L1BatchWithMetadata, L1BatchNumber}; @@ -120,6 +121,26 @@ impl<'a> Connection<'a> { ctx: &ctx::Ctx, cert: &attester::BatchQC, ) -> Result<(), InsertCertificateError> { + use crate::storage::consensus_dal::InsertCertificateError as E; + + let l1_batch_number = L1BatchNumber(cert.message.number.0 as u32); + + let Some(l1_batch) = self + .0 + .blocks_dal() + .get_l1_batch_metadata(l1_batch_number) + .await + .map_err(E::Dal)? + else { + return Err(E::MissingPayload.into()); + }; + + let l1_batch_info = StoredBatchInfo::from(&l1_batch); + + if l1_batch_info.hash().0 != *cert.message.hash.0.as_bytes() { + return Err(E::PayloadMismatch.into()); + } + Ok(ctx .wait(self.0.consensus_dal().insert_batch_certificate(cert)) .await??)