1use hex::{DisplayHex, FromHex};
5use serde::{de::Error, Deserialize, Deserializer, Serialize, Serializer};
6
7use crate::Descriptor;
8
9impl Serialize for Descriptor {
10 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
11 where
12 S: Serializer,
13 {
14 let bytes = self.to_bytes();
16 if serializer.is_human_readable() {
17 bytes.to_lower_hex_string().serialize(serializer)
19 } else {
20 bytes.serialize(serializer)
22 }
23 }
24}
25
26impl<'de> Deserialize<'de> for Descriptor {
27 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
28 where
29 D: Deserializer<'de>,
30 {
31 if deserializer.is_human_readable() {
32 let hex_str = String::deserialize(deserializer)?;
34 let bytes = Vec::from_hex(&hex_str).map_err(Error::custom)?;
35 if bytes.is_empty() {
36 return Err(Error::custom("empty input"));
37 }
38 Descriptor::from_vec(bytes).map_err(Error::custom)
39 } else {
40 let bytes = Vec::<u8>::deserialize(deserializer)?;
42 if bytes.is_empty() {
43 return Err(Error::custom("empty input"));
44 }
45 Descriptor::from_vec(bytes).map_err(Error::custom)
46 }
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53 use crate::DescriptorType;
54 use std::str::FromStr;
55
56 #[cfg(test)]
57 mod proptest_tests {
58 use super::*;
59 use crate::descriptor::MAX_OP_RETURN_LEN;
60 use proptest::prelude::*;
61
62 proptest! {
63 #[test]
65 fn op_return_serialization_roundtrip_property(data in prop::collection::vec(any::<u8>(), 0..=MAX_OP_RETURN_LEN)) {
66 if data.len() <= MAX_OP_RETURN_LEN {
67 let mut bytes = vec![0u8; data.len() + 1];
68 bytes[0] = 0; bytes[1..].copy_from_slice(&data);
70
71 let descriptor = Descriptor::from_bytes(&bytes).expect("valid OP_RETURN should parse");
72
73 let json_serialized = serde_json::to_string(&descriptor).unwrap();
75 let json_deserialized: Descriptor = serde_json::from_str(&json_serialized).unwrap();
76 assert_eq!(descriptor, json_deserialized);
77
78 let bincode_serialized = bincode::serialize(&descriptor).unwrap();
80 let bincode_deserialized: Descriptor = bincode::deserialize(&bincode_serialized).unwrap();
81 assert_eq!(descriptor, bincode_deserialized);
82 }
83 }
84 }
85 }
86
87 fn test_roundtrip(descriptor: &Descriptor) {
89 let json_serialized = serde_json::to_string(&descriptor).unwrap();
91 let json_deserialized: Descriptor = serde_json::from_str(&json_serialized).unwrap();
92 assert_eq!(*descriptor, json_deserialized);
93
94 let bincode_serialized = bincode::serialize(&descriptor).unwrap();
96 let bincode_deserialized: Descriptor = bincode::deserialize(&bincode_serialized).unwrap();
97 assert_eq!(*descriptor, bincode_deserialized);
98
99 let json_bytes = serde_json::to_vec(&descriptor).unwrap();
101 assert_ne!(bincode_serialized, json_bytes);
102 }
103
104 #[test]
105 fn invalid_deserialization() {
106 let invalid_json = "\"0500000000000000000000000000000000000000000000000000000000000000\"";
108 let json_result: Result<Descriptor, _> = serde_json::from_str(invalid_json);
109 assert!(json_result.is_err());
110
111 let invalid_bytes: Vec<u8> = vec![5; 33]; let bincode_result: Result<Descriptor, _> = bincode::deserialize(&invalid_bytes);
114 assert!(bincode_result.is_err());
115
116 let empty_json_result: Result<Descriptor, _> = serde_json::from_str("\"\"");
118 let empty_bincode_result: Result<Descriptor, _> = bincode::deserialize::<Descriptor>(&[]);
119 assert!(empty_json_result.is_err());
120 assert!(empty_bincode_result.is_err());
121 }
122
123 #[test]
124 fn serde_op_return() {
125 let descriptor = Descriptor::from_str("00636861726c6579206c6f766573206865696469").unwrap();
130
131 test_roundtrip(&descriptor);
132 assert_eq!(descriptor.type_tag(), DescriptorType::OpReturn);
133 assert_eq!(descriptor.payload(), b"charley loves heidi");
134 }
135
136 #[test]
137 fn serde_p2pkh() {
138 let descriptor =
143 Descriptor::from_str("01b8268ce4d481413c4e848ff353cd16104291c45b").unwrap();
144
145 test_roundtrip(&descriptor);
146 assert_eq!(descriptor.type_tag(), DescriptorType::P2pkh);
147 }
148
149 #[test]
150 fn serde_p2sh() {
151 let descriptor =
156 Descriptor::from_str("02748284390f9e263a4b766a75d0633c50426eb875").unwrap();
157
158 test_roundtrip(&descriptor);
159 assert_eq!(descriptor.type_tag(), DescriptorType::P2sh);
160 }
161
162 #[test]
163 fn serde_p2wpkh() {
164 let descriptor =
168 Descriptor::from_str("03671041727b982843f7e3db4669c2f542e05096fb").unwrap();
169
170 test_roundtrip(&descriptor);
171 assert_eq!(descriptor.type_tag(), DescriptorType::P2wpkh);
172 }
173
174 #[test]
175 fn serde_p2wsh() {
176 let descriptor = Descriptor::from_str(
181 "0365f91a53cb7120057db3d378bd0f7d944167d43a7dcbff15d6afc4823f1d3ed3",
182 )
183 .unwrap();
184
185 test_roundtrip(&descriptor);
186 assert_eq!(descriptor.type_tag(), DescriptorType::P2wsh);
187 }
188
189 #[test]
190 fn serde_p2a() {
191 let descriptor = Descriptor::from_str("04").unwrap();
196
197 test_roundtrip(&descriptor);
198 assert_eq!(descriptor.type_tag(), DescriptorType::P2a);
199 }
200
201 #[test]
202 fn serde_p2tr() {
203 let descriptor = Descriptor::from_str(
208 "040f0c8db753acbd17343a39c2f3f4e35e4be6da749f9e35137ab220e7b238a667",
209 )
210 .unwrap();
211
212 test_roundtrip(&descriptor);
213 assert_eq!(descriptor.type_tag(), DescriptorType::P2tr);
214 }
215
216 #[test]
217 fn compare_serialization_formats() {
218 let descriptor = Descriptor::from_str(
223 "040f0c8db753acbd17343a39c2f3f4e35e4be6da749f9e35137ab220e7b238a667",
224 )
225 .unwrap();
226
227 let json_bytes = serde_json::to_vec(&descriptor).unwrap();
229 let bincode_bytes = bincode::serialize(&descriptor).unwrap();
230
231 assert_ne!(json_bytes, bincode_bytes);
233
234 let json_deserialized: Descriptor = serde_json::from_slice(&json_bytes).unwrap();
236 let bincode_deserialized: Descriptor = bincode::deserialize(&bincode_bytes).unwrap();
237
238 assert_eq!(descriptor, json_deserialized);
239 assert_eq!(descriptor, bincode_deserialized);
240 }
241
242 #[test]
243 fn test_human_readable_format() {
244 let descriptor = Descriptor::from_str(
249 "040f0c8db753acbd17343a39c2f3f4e35e4be6da749f9e35137ab220e7b238a667",
250 )
251 .unwrap();
252
253 let json_string = serde_json::to_string(&descriptor).unwrap();
255
256 assert!(json_string
258 .chars()
259 .all(|c| c.is_ascii_hexdigit() || c == '"'));
260
261 let deserialized: Descriptor = serde_json::from_str(&json_string).unwrap();
263 assert_eq!(descriptor, deserialized);
264 }
265}