Skip to main content

starknet_devnet_types/rpc/
proof.rs

1use base64::Engine;
2use serde::{Deserialize, Deserializer, Serialize, Serializer};
3
4/// Proof represented as a vector of u8 values.
5/// When serialized, it's encoded as a base64 string for compact representation.
6/// When deserialized, it accepts both base64 strings and arrays of u8 values.
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct Proof(pub Vec<u8>);
9
10impl Proof {
11    pub fn new(data: Vec<u8>) -> Self {
12        Self(data)
13    }
14
15    pub fn inner(&self) -> &Vec<u8> {
16        &self.0
17    }
18
19    pub fn into_inner(self) -> Vec<u8> {
20        self.0
21    }
22
23    pub fn len(&self) -> usize {
24        self.0.len()
25    }
26
27    pub fn is_empty(&self) -> bool {
28        self.0.is_empty()
29    }
30}
31
32impl From<Vec<u8>> for Proof {
33    fn from(data: Vec<u8>) -> Self {
34        Self(data)
35    }
36}
37
38impl From<Proof> for Vec<u8> {
39    fn from(proof: Proof) -> Self {
40        proof.0
41    }
42}
43
44impl AsRef<[u8]> for Proof {
45    fn as_ref(&self) -> &[u8] {
46        &self.0
47    }
48}
49
50impl Serialize for Proof {
51    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
52    where
53        S: Serializer,
54    {
55        let base64_string = base64::engine::general_purpose::STANDARD.encode(&self.0);
56        serializer.serialize_str(&base64_string)
57    }
58}
59
60impl<'de> Deserialize<'de> for Proof {
61    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
62    where
63        D: Deserializer<'de>,
64    {
65        use serde::de::Error;
66
67        #[derive(Deserialize)]
68        #[serde(untagged)]
69        enum ProofFormat {
70            Base64(String),
71            Array(Vec<u8>),
72        }
73
74        match ProofFormat::deserialize(deserializer)? {
75            ProofFormat::Base64(s) => {
76                let bytes = base64::engine::general_purpose::STANDARD
77                    .decode(&s)
78                    .map_err(|e| D::Error::custom(format!("Invalid base64: {}", e)))?;
79
80                Ok(Proof(bytes))
81            }
82            ProofFormat::Array(vec) => Ok(Proof(vec)),
83        }
84    }
85}
86
87#[cfg(test)]
88mod tests {
89    use serde_json;
90
91    use super::*;
92
93    #[test]
94    fn test_serialize_proof_as_base64() {
95        let proof = Proof(vec![0x12, 0xAB, 0x44, 0x88]);
96        let serialized = serde_json::to_string(&proof).unwrap();
97
98        // Should be a base64 string, not an array
99        assert!(serialized.starts_with('"'));
100        assert!(serialized.ends_with('"'));
101        assert!(!serialized.contains('['));
102    }
103
104    #[test]
105    fn test_deserialize_proof_from_base64() {
106        let original = Proof(vec![0x12, 0xAB, 0x44, 0x88]);
107        let serialized = serde_json::to_string(&original).unwrap();
108        let deserialized: Proof = serde_json::from_str(&serialized).unwrap();
109
110        assert_eq!(original, deserialized);
111    }
112
113    #[test]
114    fn test_deserialize_proof_from_array() {
115        let json = "[18,171,68,136]";
116        let proof: Proof = serde_json::from_str(json).unwrap();
117
118        assert_eq!(proof.0, vec![0x12, 0xAB, 0x44, 0x88]);
119    }
120
121    #[test]
122    fn test_roundtrip_serialization() {
123        let original = Proof(vec![1, 2, 3, 4, 5, 6, 7, 8]);
124        let serialized = serde_json::to_string(&original).unwrap();
125        let deserialized: Proof = serde_json::from_str(&serialized).unwrap();
126
127        assert_eq!(original, deserialized);
128    }
129
130    #[test]
131    fn test_empty_proof() {
132        let proof = Proof(vec![]);
133        let serialized = serde_json::to_string(&proof).unwrap();
134        let deserialized: Proof = serde_json::from_str(&serialized).unwrap();
135
136        assert_eq!(proof, deserialized);
137        assert!(deserialized.0.is_empty());
138    }
139
140    #[test]
141    fn test_invalid_base64() {
142        let json = "\"not valid base64!!!\"";
143        let result = serde_json::from_str::<Proof>(json);
144
145        assert!(result.is_err());
146    }
147
148    #[test]
149    fn test_any_length_base64_is_valid() {
150        // Any byte length is valid for Vec<u8>
151        let bytes = vec![1, 2, 3, 4, 5];
152        let base64_string = base64::engine::general_purpose::STANDARD.encode(&bytes);
153        let json = format!("\"{}\"", base64_string);
154        let result: Proof = serde_json::from_str(&json).unwrap();
155
156        assert_eq!(result.0, bytes);
157    }
158}