Skip to content

Commit 23075f3

Browse files
starknet_api: add PROOF_VERSION_V1 and accept either marker in ProofFactsVariant
1 parent 69ce1ec commit 23075f3

3 files changed

Lines changed: 91 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: 58 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,47 @@ 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+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
645+
pub enum ProofVersion {
646+
V0,
647+
V1,
648+
}
649+
650+
impl ProofVersion {
651+
/// Felt (Cairo short-string) representation written into proof facts.
652+
pub const fn as_felt(self) -> Felt {
653+
match self {
654+
ProofVersion::V0 => PROOF_VERSION_V0,
655+
ProofVersion::V1 => PROOF_VERSION_V1,
656+
}
657+
}
658+
659+
/// Human-readable short-string label (matches the Cairo constant value).
660+
pub const fn as_str(self) -> &'static str {
661+
match self {
662+
ProofVersion::V0 => "PROOF0",
663+
ProofVersion::V1 => "PROOF1",
664+
}
665+
}
666+
}
667+
668+
impl TryFrom<Felt> for ProofVersion {
669+
type Error = Felt;
670+
fn try_from(value: Felt) -> Result<Self, Self::Error> {
671+
if value == PROOF_VERSION_V0 {
672+
Ok(ProofVersion::V0)
673+
} else if value == PROOF_VERSION_V1 {
674+
Ok(ProofVersion::V1)
675+
} else {
676+
Err(value)
677+
}
678+
}
679+
}
680+
636681
/// The version of the virtual OS output (short string 'VIRTUAL_SNOS0').
637682
/// This must match the Cairo constant `VIRTUAL_OS_OUTPUT_VERSION` in `virtual_os_output.cairo`.
638683
pub const VIRTUAL_OS_OUTPUT_VERSION: Felt =
@@ -681,13 +726,17 @@ impl TryFrom<&ProofFacts> for ProofFactsVariant {
681726
)));
682727
};
683728

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-
}
729+
// Validate that the first element is a supported proof version marker.
730+
let proof_version = ProofVersion::try_from(*proof_version).map_err(|proof_version| {
731+
StarknetApiError::InvalidProofFacts(format!(
732+
"Expected first field to be {} ({}) or {} ({}), but got {}",
733+
ProofVersion::V0.as_felt(),
734+
ProofVersion::V0.as_str(),
735+
ProofVersion::V1.as_felt(),
736+
ProofVersion::V1.as_str(),
737+
proof_version,
738+
))
739+
})?;
691740

692741
// Validate that the second element is VIRTUAL_SNOS.
693742
if *variant_marker != VIRTUAL_SNOS {
@@ -725,7 +774,7 @@ impl TryFrom<&ProofFacts> for ProofFactsVariant {
725774
})?);
726775

727776
Ok(ProofFactsVariant::Snos(SnosProofFacts {
728-
proof_version: *proof_version,
777+
proof_version,
729778
program_hash: *program_hash,
730779
block_number,
731780
block_hash: BlockHash(*block_hash),
@@ -738,7 +787,7 @@ impl TryFrom<&ProofFacts> for ProofFactsVariant {
738787
///
739788
/// A valid SNOS proof facts structure must include these fields as its first five entries.
740789
pub struct SnosProofFacts {
741-
pub proof_version: Felt,
790+
pub proof_version: ProofVersion,
742791
pub program_hash: StarkHash,
743792
pub block_number: BlockNumber,
744793
pub block_hash: BlockHash,
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use rstest::rstest;
2+
3+
use super::*;
4+
5+
/// Returns SNOS-shaped `ProofFacts` whose first felt is the given proof version.
6+
fn proof_facts_given_proof_version(proof_version: ProofVersion) -> ProofFacts {
7+
let mut facts = ProofFacts::snos_proof_facts_for_testing();
8+
Arc::make_mut(&mut facts.0)[0] = proof_version.as_felt();
9+
facts
10+
}
11+
12+
#[rstest]
13+
#[case::v0(ProofVersion::V0)]
14+
#[case::v1(ProofVersion::V1)]
15+
fn proof_facts_variant_accepts_supported_versions(#[case] version: ProofVersion) {
16+
let variant = ProofFactsVariant::try_from(&proof_facts_given_proof_version(version))
17+
.expect("supported version should parse");
18+
match variant {
19+
ProofFactsVariant::Snos(snos) => assert_eq!(snos.proof_version, version),
20+
ProofFactsVariant::Empty => panic!("expected Snos variant"),
21+
}
22+
}
23+
24+
#[test]
25+
fn proof_facts_variant_rejects_unknown_version() {
26+
let mut facts = ProofFacts::snos_proof_facts_for_testing();
27+
Arc::make_mut(&mut facts.0)[0] = Felt::from_hex_unchecked("0xDEAD");
28+
assert!(matches!(
29+
ProofFactsVariant::try_from(&facts),
30+
Err(StarknetApiError::InvalidProofFacts(_))
31+
));
32+
}

0 commit comments

Comments
 (0)