Skip to content

Commit

Permalink
Store starknet_version (#814)
Browse files Browse the repository at this point in the history
* Store starknet_version

* CR fixes
  • Loading branch information
dan-starkware authored Jul 18, 2023
1 parent ea83fb5 commit 8d492e8
Show file tree
Hide file tree
Showing 13 changed files with 251 additions and 64 deletions.
18 changes: 9 additions & 9 deletions Cargo.lock

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

Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ async fn main() {
let mut block_marker = initial_block_number;
let block_stream = central_source.stream_new_blocks(block_marker, last_block_number).fuse();
pin_mut!(block_stream);
while let Some(Ok((block_number, _block))) = block_stream.next().await {
while let Some(Ok((block_number, _block, _starknet_version))) = block_stream.next().await {
assert!(
block_marker == block_number,
"Expected block number ({block_marker}) does not match the result ({block_number}).",
Expand Down
75 changes: 75 additions & 0 deletions crates/papyrus_storage/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@
#[path = "header_test.rs"]
mod header_test;

use std::fmt::Display;

use serde::{Deserialize, Serialize};
use starknet_api::block::{BlockHash, BlockHeader, BlockNumber};
use tracing::debug;

Expand All @@ -56,6 +59,12 @@ pub trait HeaderStorageReader {
&self,
block_hash: &BlockHash,
) -> StorageResult<Option<BlockNumber>>;

/// Returns the Starknet version at the given block number.
fn get_starknet_version(
&self,
block_number: BlockNumber,
) -> StorageResult<Option<StarknetVersion>>;
}

/// Interface for writing data related to the block headers.
Expand All @@ -71,11 +80,22 @@ where
block_header: &BlockHeader,
) -> StorageResult<Self>;

/// Update the starknet version if needed.
fn update_starknet_version(
self,
block_number: &BlockNumber,
starknet_version: &StarknetVersion,
) -> StorageResult<Self>;

/// Removes a block header from the storage and returns the removed data.
fn revert_header(self, block_number: BlockNumber)
-> StorageResult<(Self, Option<BlockHeader>)>;
}

/// A version of the Starknet protocol used when creating a block.
#[derive(Clone, Debug, Eq, PartialEq, Deserialize, Serialize)]
pub struct StarknetVersion(pub String);

impl<'env, Mode: TransactionKind> HeaderStorageReader for StorageTxn<'env, Mode> {
fn get_header_marker(&self) -> StorageResult<BlockNumber> {
let markers_table = self.txn.open_table(&self.tables.markers)?;
Expand All @@ -96,6 +116,28 @@ impl<'env, Mode: TransactionKind> HeaderStorageReader for StorageTxn<'env, Mode>
let block_number = block_hash_to_number_table.get(&self.txn, block_hash)?;
Ok(block_number)
}

fn get_starknet_version(
&self,
block_number: BlockNumber,
) -> StorageResult<Option<StarknetVersion>> {
if block_number >= self.get_header_marker()? {
return Ok(None);
}

let starknet_version_table = self.txn.open_table(&self.tables.starknet_version)?;
let mut cursor = starknet_version_table.cursor(&self.txn)?;
cursor.lower_bound(&block_number.next())?;
let res = cursor.prev()?;

match res {
Some((_block_number, starknet_version)) => Ok(Some(starknet_version)),
None => unreachable!(
"Since block_number >= self.get_header_marker(), starknet_version_table should \
have at least a single mapping."
),
}
}
}

impl<'env> HeaderStorageWriter for StorageTxn<'env, RW> {
Expand All @@ -115,6 +157,27 @@ impl<'env> HeaderStorageWriter for StorageTxn<'env, RW> {

// Write mapping.
update_hash_mapping(&self.txn, &block_hash_to_number_table, block_header, block_number)?;

Ok(self)
}

fn update_starknet_version(
self,
block_number: &BlockNumber,
starknet_version: &StarknetVersion,
) -> StorageResult<Self> {
let starknet_version_table = self.txn.open_table(&self.tables.starknet_version)?;
let mut cursor = starknet_version_table.cursor(&self.txn)?;
cursor.lower_bound(block_number)?;
let res = cursor.prev()?;

match res {
Some((_block_number, last_starknet_version))
if last_starknet_version == *starknet_version => {}
_ => {
starknet_version_table.insert(&self.txn, block_number, starknet_version)?;
}
}
Ok(self)
}

Expand Down Expand Up @@ -181,3 +244,15 @@ fn update_marker<'env>(
markers_table.upsert(txn, &MarkerKind::Header, &block_number.next())?;
Ok(())
}

impl Default for StarknetVersion {
fn default() -> Self {
Self("0.0.0".to_string())
}
}

impl Display for StarknetVersion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
90 changes: 89 additions & 1 deletion crates/papyrus_storage/src/header_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use starknet_api::block::{BlockHash, BlockHeader, BlockNumber};
use starknet_api::hash::StarkFelt;
use starknet_api::stark_felt;

use crate::header::{HeaderStorageReader, HeaderStorageWriter};
use crate::header::{HeaderStorageReader, HeaderStorageWriter, StarknetVersion};
use crate::test_utils::get_test_storage;
use crate::{StorageError, StorageWriter};

Expand Down Expand Up @@ -138,3 +138,91 @@ fn append_2_headers(writer: &mut StorageWriter) {
.commit()
.unwrap();
}

#[tokio::test]
async fn starknet_version() {
fn block_header(hash: u8) -> BlockHeader {
BlockHeader { block_hash: BlockHash(stark_felt!(hash)), ..BlockHeader::default() }
}

let ((reader, mut writer), _temp_dir) = get_test_storage();

let initial_starknet_version =
reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(0)).unwrap();
assert!(initial_starknet_version.is_none());

writer
.begin_rw_txn()
.unwrap()
.append_header(BlockNumber(0), &block_header(0))
.unwrap()
.update_starknet_version(&BlockNumber(0), &StarknetVersion::default())
.unwrap()
.commit()
.unwrap();

let block_0_starknet_version =
reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(0)).unwrap();
assert_eq!(block_0_starknet_version.unwrap(), StarknetVersion::default());

let non_existing_block_starknet_version =
reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(1)).unwrap();
assert!(non_existing_block_starknet_version.is_none());

let second_version = StarknetVersion("second_version".to_string());
let yet_another_version = StarknetVersion("yet_another_version".to_string());

writer
.begin_rw_txn()
.unwrap()
.append_header(BlockNumber(1), &block_header(1))
.unwrap()
.update_starknet_version(&BlockNumber(1), &StarknetVersion::default())
.unwrap()
.append_header(BlockNumber(2), &block_header(2))
.unwrap()
.update_starknet_version(&BlockNumber(2), &second_version)
.unwrap()
.append_header(BlockNumber(3), &block_header(3))
.unwrap()
.update_starknet_version(&BlockNumber(3), &second_version)
.unwrap()
.append_header(BlockNumber(4), &block_header(4))
.unwrap()
.update_starknet_version(&BlockNumber(4), &yet_another_version)
.unwrap()
.append_header(BlockNumber(5), &block_header(5))
.unwrap()
.update_starknet_version(&BlockNumber(5), &yet_another_version)
.unwrap()
.commit()
.unwrap();

let block_0_starknet_version =
reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(0)).unwrap();
assert_eq!(block_0_starknet_version.unwrap(), StarknetVersion::default());

let block_1_starknet_version =
reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(1)).unwrap();
assert_eq!(block_1_starknet_version.unwrap(), StarknetVersion::default());

let block_2_starknet_version =
reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(2)).unwrap();
assert_eq!(block_2_starknet_version.unwrap(), second_version);

let block_3_starknet_version =
reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(3)).unwrap();
assert_eq!(block_3_starknet_version.unwrap(), second_version);

let block_4_starknet_version =
reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(4)).unwrap();
assert_eq!(block_4_starknet_version.unwrap(), yet_another_version);

let block_5_starknet_version =
reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(5)).unwrap();
assert_eq!(block_5_starknet_version.unwrap(), yet_another_version);

let block_6_starknet_version =
reader.begin_ro_txn().unwrap().get_starknet_version(BlockNumber(6)).unwrap();
assert!(block_6_starknet_version.is_none());
}
5 changes: 4 additions & 1 deletion crates/papyrus_storage/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
//! ```
//! use papyrus_storage::open_storage;
//! use papyrus_storage::db::DbConfig;
//! use papyrus_storage::header::{HeaderStorageReader, HeaderStorageWriter}; // Import the header API.
//! use papyrus_storage::header::{HeaderStorageReader, HeaderStorageWriter, StarknetVersion}; // Import the header API.
//! use starknet_api::block::{BlockHeader, BlockNumber};
//! use starknet_api::core::ChainId;
//!
Expand Down Expand Up @@ -88,6 +88,7 @@ use crate::db::{
open_env, DbConfig, DbError, DbReader, DbTransaction, DbWriter, TableHandle, TableIdentifier,
TransactionKind, RO, RW,
};
use crate::header::StarknetVersion;
use crate::state::data::IndexedDeprecatedContractClass;
use crate::version::{VersionStorageReader, VersionStorageWriter};

Expand Down Expand Up @@ -124,6 +125,7 @@ pub fn open_storage(db_config: DbConfig) -> StorageResult<(StorageReader, Storag
transaction_hash_to_idx: db_writer.create_table("transaction_hash_to_idx")?,
transaction_outputs: db_writer.create_table("transaction_outputs")?,
transactions: db_writer.create_table("transactions")?,
starknet_version: db_writer.create_table("starknet_version")?,
storage_version: db_writer.create_table("storage_version")?,
});
let reader = StorageReader { db_reader, tables: tables.clone() };
Expand Down Expand Up @@ -248,6 +250,7 @@ struct_field_names! {
transaction_hash_to_idx: TableIdentifier<TransactionHash, TransactionIndex>,
transaction_outputs: TableIdentifier<TransactionIndex, ThinTransactionOutput>,
transactions: TableIdentifier<TransactionIndex, Transaction>,
starknet_version: TableIdentifier<BlockNumber, StarknetVersion>,
storage_version: TableIdentifier<String, Version>
}
}
Expand Down
5 changes: 2 additions & 3 deletions crates/papyrus_storage/src/serializers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ use crate::compression_utils::{
compress, decompress, decompress_from_reader, serialize_and_compress,
};
use crate::db::serialization::{StorageSerde, StorageSerdeError};
use crate::header::StarknetVersion;
use crate::ommer::{OmmerEventKey, OmmerTransactionKey};
#[cfg(test)]
use crate::serializers::serializers_test::{create_storage_serde_test, StorageSerdeTest};
Expand Down Expand Up @@ -250,6 +251,7 @@ auto_storage_serde! {
pub param: TypedParameter,
pub offset: usize,
}
pub struct StarknetVersion(pub String);
pub struct ThinDeclareTransactionOutput {
pub actual_fee: Fee,
pub messages_sent: Vec<MessageToL1>,
Expand Down Expand Up @@ -823,6 +825,3 @@ impl StorageSerde for CasmContractClass {
})
}
}

#[cfg(test)]
create_storage_serde_test!(CasmContractClass);
2 changes: 2 additions & 0 deletions crates/papyrus_storage/src/test_instances.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ use crate::body::events::{
ThinInvokeTransactionOutput, ThinL1HandlerTransactionOutput, ThinTransactionOutput,
};
use crate::body::TransactionIndex;
use crate::header::StarknetVersion;
use crate::state::data::IndexedDeprecatedContractClass;
use crate::version::Version;
use crate::{EventIndex, MarkerKind, OmmerEventKey, OmmerTransactionKey};
Expand All @@ -29,6 +30,7 @@ auto_impl_get_test_instance! {
}
struct OmmerTransactionKey(pub BlockHash, pub TransactionOffsetInBlock);
struct OmmerEventKey(pub OmmerTransactionKey, pub EventIndexInTransactionOutput);
pub struct StarknetVersion(pub String);
pub struct ThinDeclareTransactionOutput {
pub actual_fee: Fee,
pub messages_sent: Vec<MessageToL1>,
Expand Down
Loading

0 comments on commit 8d492e8

Please sign in to comment.