Skip to content

Commit

Permalink
feat(sync): verifications
Browse files Browse the repository at this point in the history
  • Loading branch information
yair-starkware committed May 6, 2024
1 parent 1ace88e commit df9f417
Show file tree
Hide file tree
Showing 9 changed files with 556 additions and 92 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

75 changes: 15 additions & 60 deletions crates/papyrus_common/src/block_hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,15 @@ mod block_hash_test;

use std::iter::zip;

use starknet_api::block::{BlockBody, BlockHash, BlockHeader};
use starknet_api::block::{BlockHash, BlockHeader};
use starknet_api::core::{
ChainId,
EventCommitment,
SequencerContractAddress,
TransactionCommitment,
};
use starknet_api::hash::{pedersen_hash, StarkFelt, StarkHash};
use starknet_api::transaction::{
DeployAccountTransaction,
Event,
Transaction,
TransactionHash,
TransactionOutput,
};
use starknet_api::transaction::{DeployAccountTransaction, Event, Transaction, TransactionHash};
use starknet_api::StarknetApiError;

use crate::patricia_hash_tree::calculate_root;
Expand All @@ -34,53 +28,15 @@ pub enum BlockHashError {
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, PartialOrd, Ord)]
enum BlockHashVersion {
pub enum BlockHashVersion {
V0,
V1,
V2,
V3,
}

/// Validates hash of a starknet header.
/// A hash is valid if it is the result of one of the hash functions that were ever used in
/// Starknet.
pub fn validate_header(header: &BlockHeader, chain_id: &ChainId) -> Result<bool, BlockHashError> {
for version in
[BlockHashVersion::V3, BlockHashVersion::V2, BlockHashVersion::V1, BlockHashVersion::V0]
{
if calculate_block_hash_by_version(header, version, chain_id)? == header.block_hash {
return Ok(true);
}
}
Ok(false)
}

/// Validates the body of a starknet block.
pub fn validate_body(
body: &BlockBody,
transaction_commitment: &TransactionCommitment,
event_commitment: &EventCommitment,
) -> Result<bool, BlockHashError> {
for version in
[BlockHashVersion::V3, BlockHashVersion::V2, BlockHashVersion::V1, BlockHashVersion::V0]
{
let calculated_transaction_commitment =
calculate_transaction_commitment_by_version(body, &version)?;
if calculated_transaction_commitment != *transaction_commitment {
continue;
}
let calculated_event_commitment =
calculate_event_commitment_by_version(&body.transaction_outputs, &version);
if calculated_event_commitment != *event_commitment {
continue;
}
return Ok(true);
}
Ok(false)
}

// Calculates hash of a starknet block by version, ignoring the block hash field in the given block.
fn calculate_block_hash_by_version(
pub fn calculate_block_hash_by_version(
header: &BlockHeader,
version: BlockHashVersion,
chain_id: &ChainId,
Expand Down Expand Up @@ -127,16 +83,16 @@ fn calculate_block_hash_by_version(
}

// Returns the transaction commitment.
fn calculate_transaction_commitment_by_version(
block_body: &BlockBody,
pub fn calculate_transaction_commitment_by_version(
transactions: &[Transaction],
transaction_hashes: &[TransactionHash],
version: &BlockHashVersion,
) -> Result<TransactionCommitment, BlockHashError> {
let transaction_patricia_leaves =
zip(block_body.transactions.iter(), block_body.transaction_hashes.iter())
.map(|(transaction, transaction_hash)| {
get_transaction_leaf(transaction, transaction_hash, version)
})
.collect::<Result<Vec<_>, _>>()?;
let transaction_patricia_leaves = zip(transactions.iter(), transaction_hashes.iter())
.map(|(transaction, transaction_hash)| {
get_transaction_leaf(transaction, transaction_hash, version)
})
.collect::<Result<Vec<_>, _>>()?;
let transactions_patricia_root = calculate_root(transaction_patricia_leaves);
Ok(TransactionCommitment(transactions_patricia_root))
}
Expand Down Expand Up @@ -178,15 +134,14 @@ fn get_signature_only_from_invoke(transaction: &Transaction) -> Vec<StarkFelt> {
}

// Returns the number of the events, and the Patricia root of the events.
fn calculate_event_commitment_by_version(
transaction_outputs: &[TransactionOutput],
pub fn calculate_event_commitment_by_version<'a>(
events_iterator: impl Iterator<Item = &'a Event>,
version: &BlockHashVersion,
) -> EventCommitment {
if version < &BlockHashVersion::V1 {
return EventCommitment(*ZERO);
}
let event_patricia_leaves: Vec<_> =
transaction_outputs.iter().flat_map(|output| output.events()).map(get_event_leaf).collect();
let event_patricia_leaves: Vec<_> = events_iterator.map(get_event_leaf).collect();
let event_patricia_root = calculate_root(event_patricia_leaves);
EventCommitment(event_patricia_root)
}
Expand Down
14 changes: 10 additions & 4 deletions crates/papyrus_common/src/block_hash_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,18 @@ fn validate_block_hash_util(file_name: &str, version: BlockHashVersion) {
calculate_block_hash_by_version(&block.header, version, &chain_id).unwrap();
assert_eq!(calculated_hash, block.header.block_hash);

let calculated_transaction_commitment =
calculate_transaction_commitment_by_version(&block.body, &version).unwrap();
let calculated_transaction_commitment = calculate_transaction_commitment_by_version(
&block.body.transactions,
&block.body.transaction_hashes,
&version,
)
.unwrap();
assert_eq!(calculated_transaction_commitment, block.header.transaction_commitment.unwrap());

let calculated_event_commitment =
calculate_event_commitment_by_version(&block.body.transaction_outputs, &version);
let calculated_event_commitment = calculate_event_commitment_by_version(
block.body.transaction_outputs.iter().flat_map(|output| output.events()),
&version,
);
assert_eq!(calculated_event_commitment, block.header.event_commitment.unwrap());
}

Expand Down
1 change: 1 addition & 0 deletions crates/papyrus_sync/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ futures.workspace = true
hex.workspace = true
indexmap = { workspace = true, features = ["serde"] }
itertools.workspace = true
lazy_static.workspace = true
libmdbx = { workspace = true, features = ["lifetimed-bytes"] }
lru.workspace = true
metrics.workspace = true
Expand Down
Loading

0 comments on commit df9f417

Please sign in to comment.