Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(starknet_api): the StarknetVersion type is now an enum #1376

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions crates/papyrus_rpc/src/v0_8/api/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ async fn get_block_w_full_transactions() {
let block_hash = BlockHash(random::<u64>().into());
let sequencer_address = SequencerContractAddress(random::<u64>().into());
let timestamp = BlockTimestamp(random::<u64>());
let starknet_version = StarknetVersion(vec![123]);
let starknet_version = StarknetVersion::V0_10_0;
block.header.block_hash = block_hash;
block.header.block_header_without_hash.sequencer = sequencer_address;
block.header.block_header_without_hash.timestamp = timestamp;
Expand Down Expand Up @@ -680,7 +680,7 @@ async fn get_block_w_full_transactions_and_receipts() {
let block_hash = BlockHash(random::<u64>().into());
let sequencer_address = SequencerContractAddress(random::<u64>().into());
let timestamp = BlockTimestamp(random::<u64>());
let starknet_version = StarknetVersion(vec![123]);
let starknet_version = StarknetVersion::V0_10_0;
let block_number = block.header.block_header_without_hash.block_number;
block.header.block_hash = block_hash;
block.header.block_header_without_hash.sequencer = sequencer_address;
Expand Down Expand Up @@ -882,7 +882,7 @@ async fn get_block_w_transaction_hashes() {
let block_hash = BlockHash(random::<u64>().into());
let sequencer_address = SequencerContractAddress(random::<u64>().into());
let timestamp = BlockTimestamp(random::<u64>());
let starknet_version = StarknetVersion(vec![123]);
let starknet_version = StarknetVersion::V0_10_0;
block.header.block_hash = block_hash;
block.header.block_header_without_hash.sequencer = sequencer_address;
block.header.block_header_without_hash.timestamp = timestamp;
Expand Down
4 changes: 2 additions & 2 deletions crates/papyrus_storage/src/header_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,8 @@ async fn 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(vec![2]);
let yet_another_version = StarknetVersion(vec![3]);
let second_version = StarknetVersion::V0_9_1;
let yet_another_version = StarknetVersion::V0_12_0;

writer
.begin_rw_txn()
Expand Down
22 changes: 21 additions & 1 deletion crates/papyrus_storage/src/serialization/serializers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,7 +377,27 @@ auto_storage_serde! {
pub enum StructType {
Struct = 0,
}
pub struct StarknetVersion(pub Vec<u8>);
pub enum StarknetVersion {
V0_9_1 = 0,
V0_10_0 = 1,
V0_10_1 = 2,
V0_10_2 = 3,
V0_10_3 = 4,
V0_11_0 = 5,
V0_11_0_2 = 6,
V0_11_1 = 7,
V0_11_2 = 8,
V0_12_0 = 9,
V0_12_1 = 10,
V0_12_2 = 11,
V0_12_3 = 12,
V0_13_0 = 13,
V0_13_1 = 14,
V0_13_1_1 = 15,
V0_13_2 = 16,
V0_13_2_1 = 17,
V0_13_3 = 18,
}
pub struct StateDiffCommitment(pub PoseidonHash);
pub struct Tip(pub u64);
pub struct TransactionCommitment(pub StarkHash);
Expand Down
22 changes: 21 additions & 1 deletion crates/papyrus_test_utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,27 @@ auto_impl_get_test_instance! {
MulMod = 9,
RangeCheck96 = 10,
}
pub struct StarknetVersion(pub Vec<u8>);
pub enum StarknetVersion {
V0_9_1 = 0,
V0_10_0 = 1,
V0_10_1 = 2,
V0_10_2 = 3,
V0_10_3 = 4,
V0_11_0 = 5,
V0_11_0_2 = 6,
V0_11_1 = 7,
V0_11_2 = 8,
V0_12_0 = 9,
V0_12_1 = 10,
V0_12_2 = 11,
V0_12_3 = 12,
V0_13_0 = 13,
V0_13_1 = 14,
V0_13_1_1 = 15,
V0_13_2 = 16,
V0_13_2_1 = 17,
V0_13_3 = 18,
}
pub struct Calldata(pub Arc<Vec<Felt>>);
pub struct ClassHash(pub StarkHash);
pub struct CompiledClassHash(pub StarkHash);
Expand Down
87 changes: 81 additions & 6 deletions crates/starknet_api/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,85 @@ pub struct Block {
pub body: BlockBody,
}

/// A version of the Starknet protocol used when creating a block.
#[derive(Clone, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub struct StarknetVersion(pub Vec<u8>);
macro_rules! starknet_version_enum {
(
$(($variant:ident, $major:literal, $minor:literal, $patch:literal $(, $fourth:literal)?)),+,
$latest:ident
) => {
/// A version of the Starknet protocol used when creating a block.
#[cfg_attr(any(test, feature = "testing"), derive(strum_macros::EnumIter))]
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, PartialOrd, Ord)]
pub enum StarknetVersion {
$($variant,)+
}

impl StarknetVersion {
pub const LATEST: Self = Self::$latest;
}

impl From<&StarknetVersion> for Vec<u8> {
fn from(value: &StarknetVersion) -> Self {
match value {
$(
StarknetVersion::$variant => vec![$major, $minor, $patch $(, $fourth)?],
)+
}
}
}

impl TryFrom<Vec<u8>> for StarknetVersion {
type Error = StarknetApiError;

fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
match value[..] {
$(
[$major, $minor, $patch $(, $fourth)?] => Ok(Self::$variant),
)+
_ => Err(StarknetApiError::InvalidStarknetVersion(value)),
}
}
}
}
}

starknet_version_enum! {
(V0_9_1, 0, 9, 1),
(V0_10_0, 0, 10, 0),
(V0_10_1, 0, 10, 1),
(V0_10_2, 0, 10, 2),
(V0_10_3, 0, 10, 3),
(V0_11_0, 0, 11, 0),
(V0_11_0_2, 0, 11, 0, 2),
(V0_11_1, 0, 11, 1),
(V0_11_2, 0, 11, 2),
(V0_12_0, 0, 12, 0),
(V0_12_1, 0, 12, 1),
(V0_12_2, 0, 12, 2),
(V0_12_3, 0, 12, 3),
(V0_13_0, 0, 13, 0),
(V0_13_1, 0, 13, 1),
(V0_13_1_1, 0, 13, 1, 1),
(V0_13_2, 0, 13, 2),
(V0_13_2_1, 0, 13, 2, 1),
(V0_13_3, 0, 13, 3),
V0_13_3
}

impl Default for StarknetVersion {
fn default() -> Self {
Self(vec![0, 0, 0])
Self::LATEST
}
}

impl From<StarknetVersion> for Vec<u8> {
fn from(value: StarknetVersion) -> Self {
Vec::<u8>::from(&value)
}
}

impl Display for StarknetVersion {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0.iter().map(|x| x.to_string()).join("."))
write!(f, "{}", Vec::<u8>::from(self).iter().map(|x| x.to_string()).join("."))
}
}

Expand All @@ -57,7 +123,16 @@ impl TryFrom<String> for StarknetVersion {

/// Parses a string separated by dots into a StarknetVersion.
fn try_from(starknet_version: String) -> Result<Self, StarknetApiError> {
Ok(Self(starknet_version.split('.').map(|x| x.parse::<u8>()).try_collect()?))
let version: Vec<u8> =
starknet_version.split('.').map(|x| x.parse::<u8>()).try_collect()?;
Ok(Self::try_from(version)?)
}
}

impl TryFrom<&str> for StarknetVersion {
type Error = StarknetApiError;
fn try_from(starknet_version: &str) -> Result<Self, StarknetApiError> {
Self::try_from(starknet_version.to_string())
}
}

Expand Down
4 changes: 2 additions & 2 deletions crates/starknet_api/src/block_hash/block_hash_calculator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ pub enum BlockHashVersion {
impl From<BlockHashVersion> for StarknetVersion {
fn from(value: BlockHashVersion) -> Self {
match value {
BlockHashVersion::VO_13_2 => StarknetVersion(vec![0, 13, 2]),
BlockHashVersion::VO_13_3 => StarknetVersion(vec![0, 13, 3]),
BlockHashVersion::VO_13_2 => StarknetVersion::V0_13_2,
BlockHashVersion::VO_13_3 => StarknetVersion::V0_13_3,
}
}
}
Expand Down
31 changes: 19 additions & 12 deletions crates/starknet_api/src/block_test.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use serde_json::json;
use strum::IntoEnumIterator;

use super::{verify_block_signature, StarknetVersion};
use crate::block::{BlockHash, BlockNumber, BlockSignature};
Expand Down Expand Up @@ -49,18 +50,24 @@ fn block_signature_verification() {
}

#[test]
fn test_vec_version() {
assert_eq!(StarknetVersion::default().to_string(), "0.0.0");

let version_123 = StarknetVersion::try_from("1.2.3".to_owned()).unwrap();
assert_eq!(version_123, StarknetVersion(vec![1, 2, 3]));
fn test_version_serde() {
for version in StarknetVersion::iter() {
// To/from Vec<u8>.
assert_eq!(StarknetVersion::try_from(Vec::<u8>::from(&version)).unwrap(), version);
// To/from json.
assert_eq!(serde_json::from_value::<StarknetVersion>(json!(version)).unwrap(), version);
}

let serialized_123 = json!(version_123);
assert_eq!(serialized_123, "1.2.3".to_owned());
assert_eq!(serde_json::from_value::<StarknetVersion>(serialized_123).unwrap(), version_123);
// Sanity check substring deserialization.
assert_eq!(StarknetVersion::try_from("0.13.1").unwrap(), StarknetVersion::V0_13_1);
assert_eq!(StarknetVersion::try_from("0.13.1.1").unwrap(), StarknetVersion::V0_13_1_1);
}

assert!(StarknetVersion(vec![0, 10, 0]) > StarknetVersion(vec![0, 2, 5]));
assert!(StarknetVersion(vec![0, 13, 1]) > StarknetVersion(vec![0, 12, 2]));
assert!(StarknetVersion(vec![0, 13, 0, 1]) > StarknetVersion(vec![0, 13, 0]));
assert!(StarknetVersion(vec![0, 13, 0]) > StarknetVersion(vec![0, 13]));
/// Order of version variants should match byte-vector lexicographic order.
#[test]
fn test_version_byte_vec_order() {
let versions = StarknetVersion::iter().collect::<Vec<_>>();
for i in 0..(versions.len() - 1) {
assert!(Vec::<u8>::from(versions[i]) <= Vec::<u8>::from(versions[i + 1]));
}
}
2 changes: 2 additions & 0 deletions crates/starknet_api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ pub enum StarknetApiError {
/// Missing resource type / duplicated resource type.
#[error("Missing resource type / duplicated resource type; got {0}.")]
InvalidResourceMappingInitializer(String),
#[error("Invalid Starknet version: {0:?}")]
InvalidStarknetVersion(Vec<u8>),
#[error("NonzeroGasPrice cannot be zero.")]
ZeroGasPrice,
}
Expand Down
Loading