Skip to content

Commit 239975c

Browse files
starknet_api: add PROOF_VERSION_V1 and accept either marker in ProofFactsVariant (#14012)
1 parent a45ada5 commit 239975c

3 files changed

Lines changed: 106 additions & 10 deletions

File tree

crates/blockifier/src/transaction/account_transactions_test.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2222,7 +2222,7 @@ fn test_missing_validate_entrypoint_rejects(
22222222
/// Converts SnosProofFacts to ProofFacts for testing.
22232223
fn snos_to_proof_facts(snos: SnosProofFacts) -> ProofFacts {
22242224
vec![
2225-
snos.proof_version,
2225+
snos.proof_version.as_felt(),
22262226
VIRTUAL_SNOS,
22272227
snos.program_hash,
22282228
VIRTUAL_OS_OUTPUT_VERSION,

crates/starknet_api/src/transaction/fields.rs

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ use crate::hash::StarkHash;
1414
use crate::serde_utils::PrefixedBytesAsHex;
1515
use crate::{StarknetApiError, StarknetApiResult};
1616

17+
#[cfg(test)]
18+
#[path = "fields_test.rs"]
19+
mod fields_test;
20+
1721
pub const HIGH_GAS_AMOUNT: u64 = 10000000000; // A high gas amount that should be enough for execution.
1822

1923
/// A fee.
@@ -633,6 +637,54 @@ pub const VIRTUAL_SNOS: Felt = Felt::from_hex_unchecked("0x5649525455414c5f534e4
633637
// Represent the `PROOF_VERSION_V0` marker as a Felt ('PROOF0').
634638
pub const PROOF_VERSION_V0: Felt = Felt::from_hex_unchecked("0x50524f4f4630");
635639

640+
// Represent the `PROOF_VERSION_V1` marker as a Felt ('PROOF1').
641+
pub const PROOF_VERSION_V1: Felt = Felt::from_hex_unchecked("0x50524f4f4631");
642+
643+
/// Supported proof-facts version markers.
644+
#[cfg_attr(any(test, feature = "testing"), derive(EnumIter))]
645+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
646+
pub enum ProofVersion {
647+
V0,
648+
V1,
649+
}
650+
651+
impl ProofVersion {
652+
/// Felt (Cairo short-string) representation written into proof facts.
653+
pub const fn as_felt(self) -> Felt {
654+
match self {
655+
ProofVersion::V0 => PROOF_VERSION_V0,
656+
ProofVersion::V1 => PROOF_VERSION_V1,
657+
}
658+
}
659+
660+
/// Human-readable short-string label (matches the Cairo constant value).
661+
pub const fn as_str(self) -> &'static str {
662+
match self {
663+
ProofVersion::V0 => "PROOF0",
664+
ProofVersion::V1 => "PROOF1",
665+
}
666+
}
667+
}
668+
669+
impl TryFrom<Felt> for ProofVersion {
670+
type Error = ();
671+
fn try_from(value: Felt) -> Result<Self, Self::Error> {
672+
if value == PROOF_VERSION_V0 {
673+
Ok(ProofVersion::V0)
674+
} else if value == PROOF_VERSION_V1 {
675+
Ok(ProofVersion::V1)
676+
} else {
677+
Err(())
678+
}
679+
}
680+
}
681+
682+
impl fmt::Display for ProofVersion {
683+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
684+
write!(f, "{} ({})", self.as_felt(), self.as_str())
685+
}
686+
}
687+
636688
/// The version of the virtual OS output (short string 'VIRTUAL_SNOS0').
637689
/// This must match the Cairo constant `VIRTUAL_OS_OUTPUT_VERSION` in `virtual_os_output.cairo`.
638690
pub const VIRTUAL_OS_OUTPUT_VERSION: Felt =
@@ -681,13 +733,15 @@ impl TryFrom<&ProofFacts> for ProofFactsVariant {
681733
)));
682734
};
683735

684-
// Validate that the first element is PROOF_VERSION_V0.
685-
if *proof_version != PROOF_VERSION_V0 {
686-
return Err(StarknetApiError::InvalidProofFacts(format!(
687-
"Expected first field to be {} (PROOF_VERSION_V0), but got {}",
688-
PROOF_VERSION_V0, proof_version
689-
)));
690-
}
736+
// Validate that the first element is a supported proof version marker.
737+
let proof_version = ProofVersion::try_from(*proof_version).map_err(|()| {
738+
StarknetApiError::InvalidProofFacts(format!(
739+
"Expected first field to be {} or {}, but got {}",
740+
ProofVersion::V0,
741+
ProofVersion::V1,
742+
proof_version,
743+
))
744+
})?;
691745

692746
// Validate that the second element is VIRTUAL_SNOS.
693747
if *variant_marker != VIRTUAL_SNOS {
@@ -725,7 +779,7 @@ impl TryFrom<&ProofFacts> for ProofFactsVariant {
725779
})?);
726780

727781
Ok(ProofFactsVariant::Snos(SnosProofFacts {
728-
proof_version: *proof_version,
782+
proof_version,
729783
program_hash: *program_hash,
730784
block_number,
731785
block_hash: BlockHash(*block_hash),
@@ -738,7 +792,7 @@ impl TryFrom<&ProofFacts> for ProofFactsVariant {
738792
///
739793
/// A valid SNOS proof facts structure must include these fields as its first five entries.
740794
pub struct SnosProofFacts {
741-
pub proof_version: Felt,
795+
pub proof_version: ProofVersion,
742796
pub program_hash: StarkHash,
743797
pub block_number: BlockNumber,
744798
pub block_hash: BlockHash,
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
use starknet_types_core::short_string::ShortString;
2+
use strum::IntoEnumIterator;
3+
4+
use super::*;
5+
6+
/// Returns SNOS-shaped `ProofFacts` whose first felt is the given proof version.
7+
fn proof_facts_given_proof_version(proof_version: Felt) -> ProofFacts {
8+
let mut facts = ProofFacts::snos_proof_facts_for_testing();
9+
Arc::make_mut(&mut facts.0)[0] = proof_version;
10+
facts
11+
}
12+
13+
#[test]
14+
fn proof_facts_variant_accepts_supported_versions() {
15+
for version in ProofVersion::iter() {
16+
let variant =
17+
ProofFactsVariant::try_from(&proof_facts_given_proof_version(version.as_felt()))
18+
.expect("supported version should parse");
19+
match variant {
20+
ProofFactsVariant::Snos(snos) => assert_eq!(snos.proof_version, version),
21+
ProofFactsVariant::Empty => panic!("expected Snos variant"),
22+
}
23+
}
24+
}
25+
26+
#[test]
27+
fn proof_facts_variant_rejects_unknown_version() {
28+
let facts = proof_facts_given_proof_version(Felt::from_hex_unchecked("0xDEAD"));
29+
assert!(matches!(
30+
ProofFactsVariant::try_from(&facts),
31+
Err(StarknetApiError::InvalidProofFacts(_))
32+
));
33+
}
34+
35+
#[test]
36+
fn proof_version_str_encodes_to_felt() {
37+
for version in ProofVersion::iter() {
38+
let from_short_string =
39+
Felt::from(ShortString::try_from(version.as_str()).expect("valid short string"));
40+
assert_eq!(from_short_string, version.as_felt());
41+
}
42+
}

0 commit comments

Comments
 (0)