diff --git a/Cargo.lock b/Cargo.lock index d376428492..ecfb29f8bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7958,7 +7958,7 @@ dependencies = [ [[package]] name = "starknet_api" version = "0.10.0" -source = "git+https://github.com/starkware-libs/starknet-api?rev=1fc73f22a4e4bcc453eb25bea898256bba3bdf27#1fc73f22a4e4bcc453eb25bea898256bba3bdf27" +source = "git+https://github.com/starkware-libs/starknet-api?rev=fa2cf6d6da46c43efe141e9ffc044ae9ebbf4541#fa2cf6d6da46c43efe141e9ffc044ae9ebbf4541" dependencies = [ "cairo-lang-starknet-classes", "derive_more", diff --git a/Cargo.toml b/Cargo.toml index 75d39b018f..ae8bbacfe0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -125,4 +125,4 @@ url = "2.2.2" validator = "0.12" [patch.crates-io] -starknet_api = { git = "https://github.com/starkware-libs/starknet-api", rev = "1fc73f22a4e4bcc453eb25bea898256bba3bdf27" } +starknet_api = { git = "https://github.com/starkware-libs/starknet-api", rev = "fa2cf6d6da46c43efe141e9ffc044ae9ebbf4541" } diff --git a/crates/papyrus_network/src/converters/protobuf_conversion/header.rs b/crates/papyrus_network/src/converters/protobuf_conversion/header.rs index 665be03554..b12ba4cd67 100644 --- a/crates/papyrus_network/src/converters/protobuf_conversion/header.rs +++ b/crates/papyrus_network/src/converters/protobuf_conversion/header.rs @@ -164,9 +164,14 @@ impl TryFrom for SignedBlockHeader { sequencer, timestamp, l1_da_mode, + // TODO(shahak): fill this. state_diff_commitment: None, transaction_commitment, event_commitment, + // TODO(shahak): fill this. + state_diff_length: None, + // TODO(shahak): fill this. + receipt_commitment: None, n_transactions, n_events, starknet_version, diff --git a/crates/papyrus_storage/src/deprecated/migrations.rs b/crates/papyrus_storage/src/deprecated/migrations.rs index 09b62d18a6..bfc6d304fc 100644 --- a/crates/papyrus_storage/src/deprecated/migrations.rs +++ b/crates/papyrus_storage/src/deprecated/migrations.rs @@ -4,6 +4,7 @@ use starknet_api::core::{ EventCommitment, GlobalRoot, SequencerContractAddress, + StateDiffCommitment, TransactionCommitment, }; use starknet_api::data_availability::L1DataAvailabilityMode; @@ -13,6 +14,37 @@ use crate::db::serialization::{Migratable, StorageSerde, StorageSerdeError}; use crate::header::StorageBlockHeader; impl Migratable for StorageBlockHeader { + fn try_from_older_version( + bytes: &mut impl std::io::Read, + older_version: u8, + ) -> Result { + // TODO: Once we have version 3, extract the code below to a function. + const CURRENT_VERSION: u8 = 2; + // match doesn't allow any calculations in patterns + const PREV_VERSION: u8 = CURRENT_VERSION - 1; + // match doesn't allow exclusive ranges in patterns + const BEFORE_PREV_VERSION: u8 = PREV_VERSION - 1; + + let prev_version_block_header = match older_version { + 0..=BEFORE_PREV_VERSION => { + StorageBlockHeaderV1::try_from_older_version(bytes, older_version) + } + PREV_VERSION => { + StorageBlockHeaderV1::deserialize_from(bytes).ok_or(StorageSerdeError::Migration) + } + CURRENT_VERSION.. => { + error!( + "Unable to migrate stored header from version {} to current version.", + older_version + ); + Err(StorageSerdeError::Migration) + } + }?; + Ok(prev_version_block_header.into()) + } +} + +impl Migratable for StorageBlockHeaderV1 { fn try_from_older_version( bytes: &mut impl std::io::Read, older_version: u8, @@ -30,6 +62,24 @@ impl Migratable for StorageBlockHeader { } } +#[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] +pub(crate) struct StorageBlockHeaderV1 { + pub block_hash: BlockHash, + pub parent_hash: BlockHash, + pub block_number: BlockNumber, + pub l1_gas_price: GasPricePerToken, + pub l1_data_gas_price: GasPricePerToken, + pub state_root: GlobalRoot, + pub sequencer: SequencerContractAddress, + pub timestamp: BlockTimestamp, + pub l1_da_mode: L1DataAvailabilityMode, + pub state_diff_commitment: Option, + pub transaction_commitment: Option, + pub event_commitment: Option, + pub n_transactions: Option, + pub n_events: Option, +} + // Storage headers until starknet version 0.13.1. #[derive(Debug, Default, Clone, Eq, PartialEq, Hash, Deserialize, Serialize, PartialOrd, Ord)] pub(crate) struct StorageBlockHeaderV0 { @@ -48,7 +98,30 @@ pub(crate) struct StorageBlockHeaderV0 { pub n_events: usize, } -impl From for StorageBlockHeader { +impl From for StorageBlockHeader { + fn from(v1_header: StorageBlockHeaderV1) -> Self { + Self { + block_hash: v1_header.block_hash, + parent_hash: v1_header.parent_hash, + block_number: v1_header.block_number, + l1_gas_price: v1_header.l1_gas_price, + l1_data_gas_price: v1_header.l1_data_gas_price, + state_root: v1_header.state_root, + sequencer: v1_header.sequencer, + timestamp: v1_header.timestamp, + l1_da_mode: v1_header.l1_da_mode, + state_diff_commitment: v1_header.state_diff_commitment, + state_diff_length: None, + receipt_commitment: None, + transaction_commitment: v1_header.transaction_commitment, + event_commitment: v1_header.event_commitment, + n_transactions: v1_header.n_transactions, + n_events: v1_header.n_events, + } + } +} + +impl From for StorageBlockHeaderV1 { fn from(v0_header: StorageBlockHeaderV0) -> Self { // In older versions, the transaction_commitment and event_commitment are 0 instead of None. let missing_commitments_data = v0_header.transaction_commitment diff --git a/crates/papyrus_storage/src/deprecated/migrations_test.rs b/crates/papyrus_storage/src/deprecated/migrations_test.rs index 842877bee7..6a25a28f2d 100644 --- a/crates/papyrus_storage/src/deprecated/migrations_test.rs +++ b/crates/papyrus_storage/src/deprecated/migrations_test.rs @@ -1,18 +1,43 @@ +use std::fmt::Debug; + use starknet_api::block::{BlockNumber, StarknetVersion}; use starknet_api::core::{EventCommitment, TransactionCommitment}; use starknet_api::hash::StarkFelt; use starknet_api::stark_felt; use test_log::test; +use test_utils::{get_rng, GetTestInstance}; use crate::db::serialization::VersionZeroWrapper; use crate::db::table_types::Table; -use crate::deprecated::migrations::StorageBlockHeaderV0; +use crate::deprecated::migrations::{StorageBlockHeaderV0, StorageBlockHeaderV1}; use crate::header::{HeaderStorageReader, HeaderStorageWriter}; use crate::test_utils::get_test_storage; -use crate::MarkerKind; +use crate::{MarkerKind, StorageReader, StorageWriter, ValueSerde, VersionWrapper}; + +fn write_old_headers( + writer: &mut StorageWriter, + reader: &StorageReader, + headers: &[&TVersionWrapper::Value], +) { + // No easy way to insert a deprecated version into the db. + let table_id = writer + .db_writer + .create_simple_table::(reader.tables.headers.name) + .unwrap(); + let txn = writer.begin_rw_txn().unwrap(); + let table = txn.open_table(&table_id).unwrap(); + for (i, header) in headers.iter().enumerate() { + table.insert(&txn.txn, &BlockNumber(i.try_into().unwrap()), header).unwrap(); + } + txn.open_table(&txn.tables.markers) + .unwrap() + .upsert(&txn.txn, &MarkerKind::Header, &BlockNumber(headers.len().try_into().unwrap())) + .unwrap(); + txn.commit().unwrap(); +} #[test] -fn header_v0_to_v1() { +fn header_v0_to_current() { let ((reader, mut writer), _dir) = get_test_storage(); // Insert a headers V0 to the db. let header_without_commitments = StorageBlockHeaderV0::default(); @@ -31,47 +56,76 @@ fn header_v0_to_v1() { .commit() .unwrap(); - // No easy way to insert a deprecated version into the db. - let v0_table_id = writer - .db_writer - .create_simple_table::>( - reader.tables.headers.name, - ) - .unwrap(); - let txn = writer.begin_rw_txn().unwrap(); - let v0_table = txn.open_table(&v0_table_id).unwrap(); - v0_table.insert(&txn.txn, &BlockNumber(0), &header_without_commitments).unwrap(); - v0_table.insert(&txn.txn, &BlockNumber(1), &header_with_commitments).unwrap(); - txn.open_table(&txn.tables.markers) - .unwrap() - .upsert(&txn.txn, &MarkerKind::Header, &BlockNumber(2)) - .unwrap(); - txn.commit().unwrap(); + write_old_headers::>( + &mut writer, + &reader, + &[&header_without_commitments, &header_with_commitments], + ); - // Read the headers, expecting to get the V1 version via the migration. - let header_v1_no_commitments = + // Read the headers, expecting to get the latest version via the migration. + let header_current_no_commitments = reader.begin_ro_txn().unwrap().get_block_header(BlockNumber(0)).unwrap(); - assert!(header_v1_no_commitments.is_some()); - let header_v1_no_commitments = header_v1_no_commitments.unwrap(); - assert!(header_v1_no_commitments.state_diff_commitment.is_none()); - assert!(header_v1_no_commitments.event_commitment.is_none()); - assert!(header_v1_no_commitments.n_transactions.is_none()); - assert!(header_v1_no_commitments.n_events.is_none()); + assert!(header_current_no_commitments.is_some()); + let header_current_no_commitments = header_current_no_commitments.unwrap(); + assert!(header_current_no_commitments.state_diff_commitment.is_none()); + assert!(header_current_no_commitments.event_commitment.is_none()); + assert!(header_current_no_commitments.n_transactions.is_none()); + assert!(header_current_no_commitments.n_events.is_none()); - let header_v1_with_commitments = + let header_current_with_commitments = reader.begin_ro_txn().unwrap().get_block_header(BlockNumber(1)).unwrap(); - assert!(header_v1_with_commitments.is_some()); - let header_v1_with_commitments = header_v1_with_commitments.unwrap(); + assert!(header_current_with_commitments.is_some()); + let header_current_with_commitments = header_current_with_commitments.unwrap(); // In V0 there is no state_diff_commitment. - assert!(header_v1_with_commitments.state_diff_commitment.is_none()); + assert!(header_current_with_commitments.state_diff_commitment.is_none()); assert_eq!( - header_v1_with_commitments.transaction_commitment, + header_current_with_commitments.transaction_commitment, Some(TransactionCommitment(stark_felt!("0x1"))) ); assert_eq!( - header_v1_with_commitments.event_commitment, + header_current_with_commitments.event_commitment, Some(EventCommitment(stark_felt!("0x2"))) ); - assert_eq!(header_v1_with_commitments.n_transactions, Some(3)); - assert_eq!(header_v1_with_commitments.n_events, Some(4)); + assert_eq!(header_current_with_commitments.n_transactions, Some(3)); + assert_eq!(header_current_with_commitments.n_events, Some(4)); +} + +#[test] +fn header_v1_to_current() { + let ((reader, mut writer), _dir) = get_test_storage(); + // Insert a headers V1 to the db. + let header_v1 = StorageBlockHeaderV1::get_test_instance(&mut get_rng()); + writer + .begin_rw_txn() + .unwrap() + .update_starknet_version(&BlockNumber(0), &StarknetVersion::default()) + .unwrap() + .commit() + .unwrap(); + + write_old_headers::>( + &mut writer, + &reader, + &[&header_v1], + ); + + // Read the headers, expecting to get the V1 version via the migration. + let header_current = reader.begin_ro_txn().unwrap().get_block_header(BlockNumber(0)).unwrap(); + let header_current = header_current.unwrap(); + assert!(header_current.receipt_commitment.is_none()); + assert!(header_current.state_diff_length.is_none()); + assert_eq!(header_current.block_hash, header_v1.block_hash); + assert_eq!(header_current.parent_hash, header_v1.parent_hash); + assert_eq!(header_current.block_number, header_v1.block_number); + assert_eq!(header_current.l1_gas_price, header_v1.l1_gas_price); + assert_eq!(header_current.l1_data_gas_price, header_v1.l1_data_gas_price); + assert_eq!(header_current.state_root, header_v1.state_root); + assert_eq!(header_current.sequencer, header_v1.sequencer); + assert_eq!(header_current.timestamp, header_v1.timestamp); + assert_eq!(header_current.l1_da_mode, header_v1.l1_da_mode); + assert_eq!(header_current.state_diff_commitment, header_v1.state_diff_commitment); + assert_eq!(header_current.transaction_commitment, header_v1.transaction_commitment); + assert_eq!(header_current.event_commitment, header_v1.event_commitment); + assert_eq!(header_current.n_transactions, header_v1.n_transactions); + assert_eq!(header_current.n_events, header_v1.n_events); } diff --git a/crates/papyrus_storage/src/deprecated/serializers.rs b/crates/papyrus_storage/src/deprecated/serializers.rs index b7c8d9d81a..817f374d91 100644 --- a/crates/papyrus_storage/src/deprecated/serializers.rs +++ b/crates/papyrus_storage/src/deprecated/serializers.rs @@ -3,18 +3,19 @@ use starknet_api::core::{ EventCommitment, GlobalRoot, SequencerContractAddress, + StateDiffCommitment, TransactionCommitment, }; use starknet_api::data_availability::L1DataAvailabilityMode; use crate::db::serialization::{StorageSerde, StorageSerdeError}; -use crate::deprecated::migrations::StorageBlockHeaderV0; +use crate::deprecated::migrations::{StorageBlockHeaderV0, StorageBlockHeaderV1}; use crate::serialization::serializers::auto_storage_serde; #[cfg(test)] use crate::serialization::serializers_test::{create_storage_serde_test, StorageSerdeTest}; auto_storage_serde! { - pub struct StorageBlockHeaderV0 { + pub struct StorageBlockHeaderV0 { pub block_hash: BlockHash, pub parent_hash: BlockHash, pub block_number: BlockNumber, @@ -29,4 +30,20 @@ auto_storage_serde! { pub n_transactions: usize, pub n_events: usize, } + pub struct StorageBlockHeaderV1 { + pub block_hash: BlockHash, + pub parent_hash: BlockHash, + pub block_number: BlockNumber, + pub l1_gas_price: GasPricePerToken, + pub l1_data_gas_price: GasPricePerToken, + pub state_root: GlobalRoot, + pub sequencer: SequencerContractAddress, + pub timestamp: BlockTimestamp, + pub l1_da_mode: L1DataAvailabilityMode, + pub state_diff_commitment: Option, + pub transaction_commitment: Option, + pub event_commitment: Option, + pub n_transactions: Option, + pub n_events: Option, + } } diff --git a/crates/papyrus_storage/src/deprecated/test_instances.rs b/crates/papyrus_storage/src/deprecated/test_instances.rs index d5c9110179..ed40ad356b 100644 --- a/crates/papyrus_storage/src/deprecated/test_instances.rs +++ b/crates/papyrus_storage/src/deprecated/test_instances.rs @@ -3,12 +3,13 @@ use starknet_api::core::{ EventCommitment, GlobalRoot, SequencerContractAddress, + StateDiffCommitment, TransactionCommitment, }; use starknet_api::data_availability::L1DataAvailabilityMode; use test_utils::{auto_impl_get_test_instance, GetTestInstance}; -use crate::deprecated::migrations::StorageBlockHeaderV0; +use crate::deprecated::migrations::{StorageBlockHeaderV0, StorageBlockHeaderV1}; auto_impl_get_test_instance! { pub struct StorageBlockHeaderV0 { @@ -26,4 +27,20 @@ auto_impl_get_test_instance! { pub n_transactions: usize, pub n_events: usize, } + pub struct StorageBlockHeaderV1 { + pub block_hash: BlockHash, + pub parent_hash: BlockHash, + pub block_number: BlockNumber, + pub l1_gas_price: GasPricePerToken, + pub l1_data_gas_price: GasPricePerToken, + pub state_root: GlobalRoot, + pub sequencer: SequencerContractAddress, + pub timestamp: BlockTimestamp, + pub l1_da_mode: L1DataAvailabilityMode, + pub state_diff_commitment: Option, + pub transaction_commitment: Option, + pub event_commitment: Option, + pub n_transactions: Option, + pub n_events: Option, + } } diff --git a/crates/papyrus_storage/src/header.rs b/crates/papyrus_storage/src/header.rs index 39aa91cce5..e78fafe96b 100644 --- a/crates/papyrus_storage/src/header.rs +++ b/crates/papyrus_storage/src/header.rs @@ -51,6 +51,7 @@ use starknet_api::block::{ use starknet_api::core::{ EventCommitment, GlobalRoot, + ReceiptCommitment, SequencerContractAddress, StateDiffCommitment, TransactionCommitment, @@ -77,6 +78,8 @@ pub(crate) struct StorageBlockHeader { pub state_diff_commitment: Option, pub transaction_commitment: Option, pub event_commitment: Option, + pub receipt_commitment: Option, + pub state_diff_length: Option, pub n_transactions: Option, pub n_events: Option, } @@ -173,6 +176,8 @@ impl<'env, Mode: TransactionKind> HeaderStorageReader for StorageTxn<'env, Mode> state_diff_commitment: block_header.state_diff_commitment, transaction_commitment: block_header.transaction_commitment, event_commitment: block_header.event_commitment, + receipt_commitment: block_header.receipt_commitment, + state_diff_length: block_header.state_diff_length, n_transactions: block_header.n_transactions, n_events: block_header.n_events, starknet_version, @@ -249,6 +254,8 @@ impl<'env> HeaderStorageWriter for StorageTxn<'env, RW> { state_diff_commitment: block_header.state_diff_commitment, transaction_commitment: block_header.transaction_commitment, event_commitment: block_header.event_commitment, + receipt_commitment: block_header.receipt_commitment, + state_diff_length: block_header.state_diff_length, n_transactions: block_header.n_transactions, n_events: block_header.n_events, }; @@ -353,6 +360,8 @@ impl<'env> HeaderStorageWriter for StorageTxn<'env, RW> { state_diff_commitment: reverted_header.state_diff_commitment, transaction_commitment: reverted_header.transaction_commitment, event_commitment: reverted_header.event_commitment, + receipt_commitment: reverted_header.receipt_commitment, + state_diff_length: reverted_header.state_diff_length, n_transactions: reverted_header.n_transactions, n_events: reverted_header.n_events, starknet_version, diff --git a/crates/papyrus_storage/src/lib.rs b/crates/papyrus_storage/src/lib.rs index 8070647ad6..8c55a63475 100644 --- a/crates/papyrus_storage/src/lib.rs +++ b/crates/papyrus_storage/src/lib.rs @@ -496,7 +496,7 @@ struct_field_names! { deprecated_declared_classes: TableIdentifier, SimpleTable>, deployed_contracts: TableIdentifier<(ContractAddress, BlockNumber), VersionZeroWrapper, SimpleTable>, events: TableIdentifier<(ContractAddress, EventIndex), NoVersionValueWrapper, SimpleTable>, - headers: TableIdentifier, SimpleTable>, + headers: TableIdentifier, SimpleTable>, markers: TableIdentifier, SimpleTable>, nonces: TableIdentifier<(ContractAddress, BlockNumber), VersionZeroWrapper, SimpleTable>, file_offsets: TableIdentifier, SimpleTable>, diff --git a/crates/papyrus_storage/src/serialization/serializers.rs b/crates/papyrus_storage/src/serialization/serializers.rs index 875226127b..f0e1f1f97f 100644 --- a/crates/papyrus_storage/src/serialization/serializers.rs +++ b/crates/papyrus_storage/src/serialization/serializers.rs @@ -38,6 +38,7 @@ use starknet_api::core::{ GlobalRoot, Nonce, PatriciaKey, + ReceiptCommitment, SequencerContractAddress, StateDiffCommitment, TransactionCommitment, @@ -154,6 +155,8 @@ auto_storage_serde! { pub state_diff_commitment: Option, pub transaction_commitment: Option, pub event_commitment: Option, + pub receipt_commitment: Option, + pub state_diff_length: Option, pub n_transactions: Option, pub n_events: Option, } @@ -333,6 +336,7 @@ auto_storage_serde! { pub prime: serde_json::Value, pub reference_manager: serde_json::Value, } + pub struct ReceiptCommitment(pub StarkHash); pub enum Resource { L1Gas = 0, L2Gas = 1, diff --git a/crates/papyrus_storage/src/test_instances.rs b/crates/papyrus_storage/src/test_instances.rs index dd08876f66..478d14251c 100644 --- a/crates/papyrus_storage/src/test_instances.rs +++ b/crates/papyrus_storage/src/test_instances.rs @@ -3,6 +3,7 @@ use starknet_api::core::{ ContractAddress, EventCommitment, GlobalRoot, + ReceiptCommitment, SequencerContractAddress, StateDiffCommitment, TransactionCommitment, @@ -48,6 +49,8 @@ auto_impl_get_test_instance! { pub state_diff_commitment: Option, pub transaction_commitment: Option, pub event_commitment: Option, + pub receipt_commitment: Option, + pub state_diff_length: Option, pub n_transactions: Option, pub n_events: Option, } diff --git a/crates/starknet_client/src/reader/objects/block.rs b/crates/starknet_client/src/reader/objects/block.rs index ddb8ace54d..17339cb9f6 100644 --- a/crates/starknet_client/src/reader/objects/block.rs +++ b/crates/starknet_client/src/reader/objects/block.rs @@ -346,6 +346,10 @@ impl BlockOrDeprecated { state_diff_commitment: Some(StateDiffCommitment(PoseidonHash(state_diff_commitment.0))), transaction_commitment, event_commitment, + // TODO(shahak): Add receipt commitment once it's added to the FGW + receipt_commitment: None, + // TODO(shahak): Add state diff length once it's added to the FGW + state_diff_length: None, n_transactions, n_events, starknet_version: StarknetVersion(self.starknet_version()), diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index 39f5a07433..2ee8d9b506 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs @@ -59,6 +59,7 @@ use starknet_api::core::{ EventCommitment, GlobalRoot, Nonce, + ReceiptCommitment, SequencerContractAddress, StateDiffCommitment, TransactionCommitment, @@ -428,6 +429,8 @@ auto_impl_get_test_instance! { pub state_diff_commitment: Option, pub transaction_commitment: Option, pub event_commitment: Option, + pub receipt_commitment: Option, + pub state_diff_length: Option, pub n_transactions: Option, pub n_events: Option, pub starknet_version: StarknetVersion, @@ -664,6 +667,7 @@ auto_impl_get_test_instance! { pub prime: serde_json::Value, pub reference_manager: serde_json::Value, } + pub struct ReceiptCommitment(pub StarkHash); pub enum Resource { L1Gas = 0, L2Gas = 1,