Skip to content

Commit

Permalink
dev(block_import_refactoring): Validation -> ValidationContext
Browse files Browse the repository at this point in the history
  • Loading branch information
akhercha committed Aug 27, 2024
1 parent c08131c commit d2ee133
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 73 deletions.
21 changes: 11 additions & 10 deletions crates/client/block_import/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,11 @@
//! to check for errors.
//! A signature verification mode should be added to allow the skipping of block validation entirely if the block is signed.

use dc_db::DeoxysBackend;
use dp_validation::Validation;
use std::sync::Arc;

use dc_db::DeoxysBackend;
use dp_validation::ValidationContext;

mod error;
mod pre_validate;
mod rayon;
Expand All @@ -68,32 +69,32 @@ impl BlockImporter {
pub async fn pre_validate(
&self,
block: UnverifiedFullBlock,
validation: Validation,
validation_context: ValidationContext,
) -> Result<PreValidatedBlock, BlockImportError> {
pre_validate(&self.pool, block, validation).await
pre_validate(&self.pool, block, validation_context).await
}

pub async fn verify_apply(
&self,
block: PreValidatedBlock,
validation: Validation,
validation_context: ValidationContext,
) -> Result<BlockImportResult, BlockImportError> {
self.verify_apply.verify_apply(block, validation).await
self.verify_apply.verify_apply(block, validation_context).await
}

pub async fn pre_validate_pending(
&self,
block: UnverifiedPendingFullBlock,
validation: Validation,
validation_context: ValidationContext,
) -> Result<PreValidatedPendingBlock, BlockImportError> {
pre_validate_pending(&self.pool, block, validation).await
pre_validate_pending(&self.pool, block, validation_context).await
}

pub async fn verify_apply_pending(
&self,
block: PreValidatedPendingBlock,
validation: Validation,
validation_context: ValidationContext,
) -> Result<PendingBlockImportResult, BlockImportError> {
self.verify_apply.verify_apply_pending(block, validation).await
self.verify_apply.verify_apply_pending(block, validation_context).await
}
}
10 changes: 5 additions & 5 deletions crates/client/block_import/src/pre_validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,22 @@ use crate::{
UnverifiedPendingFullBlock,
};

use dp_validation::{PreValidate, Validation};
use dp_validation::{PreValidate, ValidationContext};

/// This function wraps the [`block.pre_validate`] step, which runs on the rayon pool, in a tokio-friendly future.
pub async fn pre_validate(
pool: &RayonPool,
block: UnverifiedFullBlock,
validation: Validation,
validation_context: ValidationContext,
) -> Result<PreValidatedBlock, BlockImportError> {
pool.spawn_rayon_task(move || block.pre_validate(&validation)).await
pool.spawn_rayon_task(move || block.pre_validate(&validation_context)).await
}

/// See [`pre_validate`].
pub async fn pre_validate_pending(
pool: &RayonPool,
block: UnverifiedPendingFullBlock,
validation: Validation,
validation_context: ValidationContext,
) -> Result<PreValidatedPendingBlock, BlockImportError> {
pool.spawn_rayon_task(move || block.pre_validate(&validation)).await
pool.spawn_rayon_task(move || block.pre_validate(&validation_context)).await
}
50 changes: 24 additions & 26 deletions crates/client/block_import/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use dp_convert::ToFelt;
use dp_receipt::TransactionReceipt;
use dp_state_update::StateDiff;
use dp_transactions::Transaction;
use dp_validation::{PreValidate, Validation};
use dp_validation::{PreValidate, ValidationContext};
use starknet_types_core::hash::{Pedersen, Poseidon, StarkHash};

use crate::BlockImportError;
Expand Down Expand Up @@ -75,11 +75,11 @@ impl PreValidate for UnverifiedPendingFullBlock {
type Output = PreValidatedPendingBlock;
type ValidationError = BlockImportError;

fn pre_validate(mut self, validation: &Validation) -> Result<Self::Output, Self::ValidationError> {
fn pre_validate(mut self, context: &ValidationContext) -> Result<Self::Output, Self::ValidationError> {
let classes = mem::take(&mut self.declared_classes);

let converted_classes = convert_classes(classes, validation)?;
let _tx_hashes = transaction_hashes(&self.receipts, &self.transactions, validation, None)?;
let converted_classes = convert_classes(classes, context)?;
let _tx_hashes = transaction_hashes(&self.receipts, &self.transactions, context, None)?;

Ok(PreValidatedPendingBlock {
header: self.header,
Expand All @@ -106,7 +106,7 @@ pub struct UnverifiedFullBlock {
}

impl UnverifiedFullBlock {
fn receipt_commitment(&self, _validation: &Validation) -> Result<Felt, BlockImportError> {
fn receipt_commitment(&self, _context: &ValidationContext) -> Result<Felt, BlockImportError> {
let hashes = self.receipts.par_iter().map(TransactionReceipt::compute_hash).collect::<Vec<_>>();
let got = compute_merkle_root::<Poseidon>(&hashes);

Expand All @@ -118,7 +118,7 @@ impl UnverifiedFullBlock {
Ok(got)
}

fn state_diff_commitment(&self, _validation: &Validation) -> Result<Felt, BlockImportError> {
fn state_diff_commitment(&self, _context: &ValidationContext) -> Result<Felt, BlockImportError> {
let got = self.state_diff.len() as u64;
if let Some(expected) = self.commitments.state_diff_length {
if expected != got {
Expand All @@ -136,11 +136,11 @@ impl UnverifiedFullBlock {
}

/// Compute the transaction commitment for a block.
fn transaction_commitment(&self, validation: &Validation) -> Result<Felt, BlockImportError> {
fn transaction_commitment(&self, context: &ValidationContext) -> Result<Felt, BlockImportError> {
let starknet_version = self.header.protocol_version;

let transaction_hashes =
transaction_hashes(&self.receipts, &self.transactions, validation, self.unverified_block_number)?;
transaction_hashes(&self.receipts, &self.transactions, context, self.unverified_block_number)?;

if let Some(expected) = self.commitments.transaction_count {
if expected != self.transactions.len() as u64 {
Expand Down Expand Up @@ -170,7 +170,7 @@ impl UnverifiedFullBlock {
Ok(got)
}

fn event_commitment(&self, _validation: &Validation) -> Result<Felt, BlockImportError> {
fn event_commitment(&self, _context: &ValidationContext) -> Result<Felt, BlockImportError> {
let events_with_tx_hash: Vec<_> = self
.receipts
.iter()
Expand Down Expand Up @@ -207,23 +207,23 @@ impl UnverifiedFullBlock {
}

/// Returns [`ValidatedCommitments`] from the block unverified commitments.
pub fn valid_commitments(&self, validation: &Validation) -> Result<ValidatedCommitments, BlockImportError> {
pub fn valid_commitments(&self, context: &ValidationContext) -> Result<ValidatedCommitments, BlockImportError> {
let (mut receipt_c, mut state_diff_c, mut transaction_c, mut event_c) = Default::default();
[
Box::new(|| {
receipt_c = self.receipt_commitment(validation)?;
receipt_c = self.receipt_commitment(context)?;
Ok(())
}) as Box<dyn FnOnce() -> Result<(), BlockImportError> + Send>,
Box::new(|| {
state_diff_c = self.state_diff_commitment(validation)?;
state_diff_c = self.state_diff_commitment(context)?;
Ok(())
}),
Box::new(|| {
transaction_c = self.transaction_commitment(validation)?;
transaction_c = self.transaction_commitment(context)?;
Ok(())
}),
Box::new(|| {
event_c = self.event_commitment(validation)?;
event_c = self.event_commitment(context)?;
Ok(())
}),
]
Expand All @@ -247,7 +247,7 @@ impl PreValidate for UnverifiedFullBlock {
type Output = PreValidatedBlock;
type ValidationError = BlockImportError;

fn pre_validate(mut self, validation: &Validation) -> Result<Self::Output, Self::ValidationError> {
fn pre_validate(mut self, context: &ValidationContext) -> Result<Self::Output, Self::ValidationError> {
let classes = mem::take(&mut self.declared_classes);

// unfortunately this is ugly but rayon::join does not have the fast error short circuiting behavior that
Expand All @@ -256,11 +256,11 @@ impl PreValidate for UnverifiedFullBlock {
let (mut commitments, mut converted_classes) = Default::default();
[
Box::new(|| {
commitments = self.valid_commitments(validation)?;
commitments = self.valid_commitments(context)?;
Ok(())
}) as Box<dyn FnOnce() -> Result<(), BlockImportError> + Send>,
Box::new(|| {
converted_classes = convert_classes(classes, validation)?;
converted_classes = convert_classes(classes, context)?;
Ok(())
}),
]
Expand Down Expand Up @@ -331,12 +331,10 @@ pub struct BlockImportResult {
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct PendingBlockImportResult {}

// Utilities for computation.

fn transaction_hashes(
receipts: &[TransactionReceipt],
transactions: &[Transaction],
validation: &Validation,
context: &ValidationContext,
block_n: Option<u64>,
) -> Result<Vec<Felt>, BlockImportError> {
if receipts.len() != transactions.len() {
Expand All @@ -348,9 +346,9 @@ fn transaction_hashes(

// mismatched block hash is allowed for blocks 1466..=2242 on mainnet
let is_special_trusted_case =
validation.chain_id == ChainId::Mainnet && block_n.is_some_and(|n| (1466..=2242).contains(&n));
context.chain_id == ChainId::Mainnet && block_n.is_some_and(|n| (1466..=2242).contains(&n));

if is_special_trusted_case || validation.trust_transaction_hashes {
if is_special_trusted_case || context.trust_transaction_hashes {
Ok(receipts.iter().map(|r| r.transaction_hash()).collect())
} else {
transactions
Expand All @@ -359,7 +357,7 @@ fn transaction_hashes(
.map(|(index, tx)| {
// Panic safety: receipt count was checked earlier
let got = receipts[index].transaction_hash();
let expected = tx.compute_hash(validation.chain_id.to_felt(), false, block_n);
let expected = tx.compute_hash(context.chain_id.to_felt(), false, block_n);
if got != expected {
return Err(BlockImportError::TransactionHash { index, got, expected });
}
Expand All @@ -371,12 +369,12 @@ fn transaction_hashes(

fn convert_classes(
declared_classes: Vec<DeclaredClass>,
validation: &Validation,
context: &ValidationContext,
) -> Result<Vec<ConvertedClass>, BlockImportError> {
declared_classes.into_par_iter().map(|class| class_conversion(class, validation)).collect()
declared_classes.into_par_iter().map(|class| class_conversion(class, context)).collect()
}

fn class_conversion(class: DeclaredClass, _validation: &Validation) -> Result<ConvertedClass, BlockImportError> {
fn class_conversion(class: DeclaredClass, _context: &ValidationContext) -> Result<ConvertedClass, BlockImportError> {
let DeclaredClass { class_hash, contract_class, compiled_class_hash } = class;

// TODO(class_hash, #212): uncomment this when the class hashes are computed correctly accross the entire state
Expand Down
22 changes: 11 additions & 11 deletions crates/client/block_import/src/verify_apply.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use dp_block::{
DeoxysMaybePendingBlockInfo, DeoxysPendingBlockInfo, Header,
};
use dp_convert::ToFelt;
use dp_validation::Validation;
use dp_validation::ValidationContext;

use crate::{
BlockImportError, BlockImportResult, PendingBlockImportResult, PreValidatedBlock, PreValidatedPendingBlock,
Expand All @@ -37,24 +37,24 @@ impl VerifyApply {
pub async fn verify_apply(
&self,
block: PreValidatedBlock,
validation: Validation,
context: ValidationContext,
) -> Result<BlockImportResult, BlockImportError> {
let _exclusive = self.mutex.lock();

let backend = Arc::clone(&self.backend);
self.pool.spawn_rayon_task(move || verify_apply_inner(&backend, block, validation)).await
self.pool.spawn_rayon_task(move || verify_apply_inner(&backend, block, context)).await
}

/// See [`Self::verify_apply`].
pub async fn verify_apply_pending(
&self,
block: PreValidatedPendingBlock,
validation: Validation,
context: ValidationContext,
) -> Result<PendingBlockImportResult, BlockImportError> {
let _exclusive = self.mutex.lock();

let backend = Arc::clone(&self.backend);
self.pool.spawn_rayon_task(move || verify_apply_pending_inner(&backend, block, validation)).await
self.pool.spawn_rayon_task(move || verify_apply_pending_inner(&backend, block, context)).await
}
}

Expand All @@ -64,7 +64,7 @@ impl VerifyApply {
pub fn verify_apply_inner(
backend: &DeoxysBackend,
block: PreValidatedBlock,
validation: Validation,
context: ValidationContext,
) -> Result<BlockImportResult, BlockImportError> {
// Check block number and block hash against db
let (block_number, parent_block_hash) =
Expand All @@ -74,7 +74,7 @@ pub fn verify_apply_inner(
let global_state_root = update_tries(backend, &block, block_number)?;

// Block hash
let (block_hash, header) = block_hash(&block, &validation, block_number, parent_block_hash, global_state_root)?;
let (block_hash, header) = block_hash(&block, &context, block_number, parent_block_hash, global_state_root)?;

// store block, also uses rayon heavily internally
backend
Expand All @@ -100,7 +100,7 @@ pub fn verify_apply_inner(
pub fn verify_apply_pending_inner(
backend: &DeoxysBackend,
block: PreValidatedPendingBlock,
_validation: Validation,
_context: ValidationContext,
) -> Result<PendingBlockImportResult, BlockImportError> {
let (_block_number, parent_block_hash) = check_parent_hash_and_num(backend, block.header.parent_block_hash, None)?;

Expand Down Expand Up @@ -224,7 +224,7 @@ fn update_tries(
/// Returns the block hash and header.
fn block_hash(
block: &PreValidatedBlock,
validation: &Validation,
context: &ValidationContext,
block_number: u64,
parent_block_hash: Felt,
global_state_root: Felt,
Expand Down Expand Up @@ -267,11 +267,11 @@ fn block_hash(
l1_gas_price,
l1_da_mode,
};
let block_hash = header.compute_hash(validation.chain_id.to_felt());
let block_hash = header.compute_hash(context.chain_id.to_felt());

if let Some(expected) = block.unverified_block_hash {
// mismatched block hash is allowed for blocks 1466..=2242 on mainnet
let is_special_trusted_case = validation.chain_id == ChainId::Mainnet && (1466..=2242).contains(&block_number);
let is_special_trusted_case = context.chain_id == ChainId::Mainnet && (1466..=2242).contains(&block_number);
if is_special_trusted_case {
return Ok((expected, header));
}
Expand Down
8 changes: 4 additions & 4 deletions crates/client/mempool/src/close_block.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use dc_block_import::{BlockImportError, BlockImportResult, BlockImporter, UnverifiedFullBlock, UnverifiedHeader};
use dp_block::{header::PendingHeader, DeoxysPendingBlock, DeoxysPendingBlockInfo};
use dp_state_update::StateDiff;
use dp_validation::Validation;
use dp_validation::ValidationContext;
use starknet_api::core::ChainId;

/// Close the block (convert from pending to closed), and store to db. This is delegated to the block import module.
Expand All @@ -12,7 +12,7 @@ pub async fn close_block(
chain_id: ChainId,
block_number: u64,
) -> Result<BlockImportResult, BlockImportError> {
let validation = Validation {
let validation_context = ValidationContext {
trust_transaction_hashes: true, // no need to recompute tx hashes
chain_id,
};
Expand Down Expand Up @@ -48,9 +48,9 @@ pub async fn close_block(
declared_classes: vec![],
commitments: Default::default(), // the block importer will compute the commitments for us
},
validation.clone(),
validation_context.clone(),
)
.await?;

importer.verify_apply(block, validation.clone()).await
importer.verify_apply(block, validation_context.clone()).await
}
Loading

0 comments on commit d2ee133

Please sign in to comment.