1pub mod array;
10mod de;
11mod prefixed_vec;
12mod ser;
13
14pub use {
15 de::{from_slice, Deserializer, DeserializerError},
16 prefixed_vec::PrefixedVec,
17 ser::{to_vec, to_writer, Serializer, SerializerError},
18};
19
20pub mod v1 {
26 use {
27 super::*,
28 crate::{
29 accumulators::merkle::MerklePath, error::Error, hashers::keccak256_160::Keccak160,
30 require,
31 },
32 borsh::{BorshDeserialize, BorshSerialize},
33 serde::{Deserialize, Serialize},
34 };
35 pub const PYTHNET_ACCUMULATOR_UPDATE_MAGIC: &[u8; 4] = b"PNAU";
36 pub const CURRENT_MINOR_VERSION: u8 = 0;
37
38 #[derive(Clone, Debug, Hash, PartialEq, Serialize, Deserialize)]
43 pub struct AccumulatorUpdateData {
44 magic: [u8; 4],
45 major_version: u8,
46 minor_version: u8,
47 trailing: Vec<u8>,
48 pub proof: Proof,
49 }
50
51 impl AccumulatorUpdateData {
52 pub fn new(proof: Proof) -> Self {
53 Self {
54 magic: *PYTHNET_ACCUMULATOR_UPDATE_MAGIC,
55 major_version: 1,
56 minor_version: 0,
57 trailing: vec![],
58 proof,
59 }
60 }
61
62 pub fn try_from_slice(bytes: &[u8]) -> Result<Self, Error> {
63 let message = from_slice::<byteorder::BE, Self>(bytes)
64 .map_err(|_| Error::DeserializationError)?;
65 require!(
66 &message.magic[..] == PYTHNET_ACCUMULATOR_UPDATE_MAGIC,
67 Error::InvalidMagic
68 );
69 require!(message.major_version == 1, Error::InvalidVersion);
70 #[allow(clippy::absurd_extreme_comparisons)]
71 {
72 require!(
73 message.minor_version >= CURRENT_MINOR_VERSION,
74 Error::InvalidVersion
75 );
76 }
77 Ok(message)
78 }
79 }
80
81 pub type Hash = [u8; 20];
83
84 #[derive(Clone, Debug, Hash, PartialEq, Serialize, Deserialize)]
85 pub enum Proof {
86 WormholeMerkle {
87 vaa: PrefixedVec<u16, u8>,
88 updates: Vec<MerklePriceUpdate>,
89 },
90 }
91
92 #[derive(
93 Clone, Debug, Hash, PartialEq, Serialize, Deserialize, BorshDeserialize, BorshSerialize,
94 )]
95 pub struct MerklePriceUpdate {
96 pub message: PrefixedVec<u16, u8>,
97 pub proof: MerklePath<Keccak160>,
98 }
99
100 #[derive(Clone, Debug, Hash, PartialEq, Serialize, Deserialize)]
101 pub struct WormholeMessage {
102 pub magic: [u8; 4],
103 pub payload: WormholePayload,
104 }
105
106 pub const ACCUMULATOR_UPDATE_WORMHOLE_VERIFICATION_MAGIC: &[u8; 4] = b"AUWV";
107
108 impl WormholeMessage {
109 pub fn new(payload: WormholePayload) -> Self {
110 Self {
111 magic: *ACCUMULATOR_UPDATE_WORMHOLE_VERIFICATION_MAGIC,
112 payload,
113 }
114 }
115
116 pub fn try_from_bytes(bytes: impl AsRef<[u8]>) -> Result<Self, Error> {
117 let message = from_slice::<byteorder::BE, Self>(bytes.as_ref())
118 .map_err(|_| Error::DeserializationError)?;
119 require!(
120 &message.magic[..] == ACCUMULATOR_UPDATE_WORMHOLE_VERIFICATION_MAGIC,
121 Error::InvalidMagic
122 );
123 Ok(message)
124 }
125 }
126
127 #[derive(Clone, Debug, Hash, PartialEq, Serialize, Deserialize)]
128 pub enum WormholePayload {
129 Merkle(WormholeMerkleRoot),
130 }
131
132 #[derive(Clone, Debug, Hash, PartialEq, Serialize, Deserialize)]
133 pub struct WormholeMerkleRoot {
134 pub slot: u64,
135 pub ring_size: u32,
136 pub root: Hash,
137 }
138}
139
140#[cfg(test)]
141mod tests {
142 use crate::wire::{
143 array,
144 v1::{AccumulatorUpdateData, Proof},
145 Deserializer, PrefixedVec, Serializer,
146 };
147
148 #[test]
150 fn test_array_serde() {
151 let mut buffer = Vec::new();
153 let mut cursor = std::io::Cursor::new(&mut buffer);
154 let mut serializer: Serializer<_, byteorder::LE> = Serializer::new(&mut cursor);
155 array::serialize(&[1u8; 37], &mut serializer).unwrap();
156
157 assert_eq!(buffer.len(), 37);
159
160 let mut deserializer = Deserializer::<byteorder::LE>::new(&buffer);
162 let deserialized: [u8; 37] = array::deserialize(&mut deserializer).unwrap();
163
164 assert_eq!(deserialized, [1u8; 37]);
166 }
167
168 #[test]
171 fn test_array_serde_json() {
172 let mut buffer = Vec::new();
174 let mut cursor = std::io::Cursor::new(&mut buffer);
175 let mut serialized = serde_json::Serializer::new(&mut cursor);
176 array::serialize(&[1u8; 7], &mut serialized).unwrap();
177 let result = String::from_utf8(buffer).unwrap();
178 assert_eq!(result, "[1,1,1,1,1,1,1]");
179
180 let mut deserializer = serde_json::Deserializer::from_str(&result);
182 let deserialized: [u8; 7] = array::deserialize(&mut deserializer).unwrap();
183 assert_eq!(deserialized, [1u8; 7]);
184 }
185
186 #[test]
195 fn test_pyth_serde() {
196 use serde::Serialize;
197
198 let mut buffer = Vec::new();
200 let mut cursor = std::io::Cursor::new(&mut buffer);
201 let mut serializer: Serializer<_, byteorder::LE> = Serializer::new(&mut cursor);
202
203 #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)]
206 struct GoldenStruct<'a> {
207 unit: (),
209
210 t_bool: bool,
212
213 t_u8: u8,
215 t_u16: u16,
216 t_u32: u32,
217 t_u64: u64,
218
219 t_string: String,
221 t_str: &'a str,
222
223 t_vec: Vec<u8>,
225 t_vec_empty: Vec<u8>,
226 t_vec_nested: Vec<Vec<u8>>,
227 t_vec_nested_empty: Vec<Vec<u8>>,
228 t_slice: &'a [u8],
229 t_slice_empty: &'a [u8],
230
231 t_tuple: (u8, u16, u32, u64, String, Vec<u8>, &'a [u8]),
233 t_tuple_nested: ((u8, u16), (u32, u64)),
234
235 t_enum_unit: GoldenEnum,
237 t_enum_newtype: GoldenEnum,
238 t_enum_tuple: GoldenEnum,
239 t_enum_struct: GoldenEnum,
240
241 t_struct: GoldenNested<u8>,
243 t_prefixed: PrefixedVec<u16, u8>,
244 }
245
246 #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)]
247 struct GoldenNested<T> {
248 nested_u8: T,
249 nested_tuple: (u8, u8),
250 }
251
252 #[derive(serde::Serialize, serde::Deserialize, Debug, PartialEq)]
253 enum GoldenEnum {
254 Unit,
255 Newtype(u8),
256 Tuple(u8, u16),
257 Struct { a: u8, b: u16 },
258 }
259
260 let golden_struct = GoldenStruct {
262 unit: (),
263 t_bool: true,
264 t_u8: 1,
265 t_u16: 2,
266 t_u32: 3,
267 t_u64: 4,
268 t_string: "9".to_string(),
269 t_str: "10",
270 t_vec: vec![11, 12, 13],
271 t_vec_empty: vec![],
272 t_vec_nested: vec![vec![14, 15, 16], vec![17, 18, 19]],
273 t_vec_nested_empty: vec![vec![], vec![]],
274 t_slice: &[20, 21, 22],
275 t_slice_empty: &[],
276 t_tuple: (
277 29,
278 30,
279 31,
280 32,
281 "10".to_string(),
282 vec![35, 36, 37],
283 &[38, 39, 40],
284 ),
285 t_tuple_nested: ((41, 42), (43, 44)),
286 t_enum_unit: GoldenEnum::Unit,
287 t_enum_newtype: GoldenEnum::Newtype(45),
288 t_enum_tuple: GoldenEnum::Tuple(46, 47),
289 t_enum_struct: GoldenEnum::Struct { a: 48, b: 49 },
290 t_struct: GoldenNested {
291 nested_u8: 50,
292 nested_tuple: (51, 52),
293 },
294 t_prefixed: vec![0u8; 512].into(),
295 };
296
297 golden_struct.serialize(&mut serializer).unwrap();
298
299 assert_eq!(
301 &buffer,
302 &[
303 1, 1, 2, 0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 1, 57, 2, 49, 48, 3, 11, 12, 13, 0, 2, 3, 14, 15, 16, 3, 17, 18, 19, 2, 0, 0, 3, 20, 21, 22, 0, 29, 30, 0, 31, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 2, 49, 48, 3, 35, 36, 37, 3, 38, 39, 40, 41, 42, 0, 43, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 1, 45, 2, 46, 47, 0, 3, 48, 49, 0, 50, 51, 52, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
330 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
331 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
332 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
333 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
334 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
335 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
336 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
337 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
338 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
339 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
340 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
341 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
342 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
343 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
344 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
345 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
346 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
347 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
348 ]
349 );
350
351 assert_eq!(
353 golden_struct,
354 crate::wire::from_slice::<byteorder::LE, _>(&buffer).unwrap()
355 );
356 }
357
358 #[test]
359 #[rustfmt::skip]
360 fn test_serde_enum_access_behaviour() {
364 use serde::Deserialize;
365 use serde::Serialize;
366
367 #[derive(PartialEq, Serialize, Deserialize, Debug)]
369 enum Singleton { A }
370
371 #[derive(PartialEq, Serialize, Deserialize, Debug)]
372 enum Pair { A, B }
373
374 #[derive(PartialEq, Serialize, Deserialize, Debug)]
375 enum Triple { A, B, C }
376
377 #[derive(PartialEq, Serialize, Deserialize, Debug)]
379 enum CustomIndices {
380 A = 33,
381 B = 55,
382 C = 255,
383 }
384
385 #[derive(PartialEq, Serialize, Deserialize, Debug)]
388 enum Complex {
389 A,
390 B(u8, u8),
391 C { a: u8, b: u8 },
392 }
393
394 #[derive(PartialEq, Serialize, Deserialize, Debug)]
398 enum ManyVariants {
399 _000, _001, _002, _003, _004, _005, _006, _007, _008, _009, _00A, _00B, _00C, _00D,
400 _00E, _00F, _010, _011, _012, _013, _014, _015, _016, _017, _018, _019, _01A, _01B,
401 _01C, _01D, _01E, _01F, _020, _021, _022, _023, _024, _025, _026, _027, _028, _029,
402 _02A, _02B, _02C, _02D, _02E, _02F, _030, _031, _032, _033, _034, _035, _036, _037,
403 _038, _039, _03A, _03B, _03C, _03D, _03E, _03F, _040, _041, _042, _043, _044, _045,
404 _046, _047, _048, _049, _04A, _04B, _04C, _04D, _04E, _04F, _050, _051, _052, _053,
405 _054, _055, _056, _057, _058, _059, _05A, _05B, _05C, _05D, _05E, _05F, _060, _061,
406 _062, _063, _064, _065, _066, _067, _068, _069, _06A, _06B, _06C, _06D, _06E, _06F,
407 _070, _071, _072, _073, _074, _075, _076, _077, _078, _079, _07A, _07B, _07C, _07D,
408 _07E, _07F, _080, _081, _082, _083, _084, _085, _086, _087, _088, _089, _08A, _08B,
409 _08C, _08D, _08E, _08F, _090, _091, _092, _093, _094, _095, _096, _097, _098, _099,
410 _09A, _09B, _09C, _09D, _09E, _09F, _0A0, _0A1, _0A2, _0A3, _0A4, _0A5, _0A6, _0A7,
411 _0A8, _0A9, _0AA, _0AB, _0AC, _0AD, _0AE, _0AF, _0B0, _0B1, _0B2, _0B3, _0B4, _0B5,
412 _0B6, _0B7, _0B8, _0B9, _0BA, _0BB, _0BC, _0BD, _0BE, _0BF, _0C0, _0C1, _0C2, _0C3,
413 _0C4, _0C5, _0C6, _0C7, _0C8, _0C9, _0CA, _0CB, _0CC, _0CD, _0CE, _0CF, _0D0, _0D1,
414 _0D2, _0D3, _0D4, _0D5, _0D6, _0D7, _0D8, _0D9, _0DA, _0DB, _0DC, _0DD, _0DE, _0DF,
415 _0E0, _0E1, _0E2, _0E3, _0E4, _0E5, _0E6, _0E7, _0E8, _0E9, _0EA, _0EB, _0EC, _0ED,
416 _0EE, _0EF, _0F0, _0F1, _0F2, _0F3, _0F4, _0F5, _0F6, _0F7, _0F8, _0F9, _0FA, _0FB,
417 _0FC, _0FD, _0FE, _0FF,
418
419 _100
421 }
422
423 #[derive(PartialEq, Serialize, Deserialize, Debug)]
424 struct AllValid {
425 singleton: Singleton,
426 pair: Pair,
427 triple: Triple,
428 complex: Complex,
429 custom: CustomIndices,
430 }
431
432 #[derive(PartialEq, Serialize, Deserialize, Debug)]
433 struct Invalid {
434 many_variants: ManyVariants,
435 }
436
437 let valid_buffer = [
438 0,
440 1,
442 2,
444 1, 0, 0,
446 2,
448 ];
449
450 let valid_struct = AllValid {
451 singleton: Singleton::A,
452 pair: Pair::B,
453 triple: Triple::C,
454 complex: Complex::B(0, 0),
455 custom: CustomIndices::C,
456 };
457
458 let valid_serialized = crate::wire::ser::to_vec::<_, byteorder::BE>(&valid_struct).unwrap();
459
460 let valid = crate::wire::from_slice::<byteorder::BE, AllValid>(&valid_buffer).unwrap();
462 let valid_deserialized = crate::wire::from_slice::<byteorder::BE, AllValid>(&valid_serialized).unwrap();
463 assert_eq!(valid, valid_struct);
464 assert_eq!(valid_deserialized, valid_struct);
465
466 let invalid_buffer = [
470 1, 0
472 ];
473
474 let result = crate::wire::from_slice::<byteorder::BE, Invalid>(&invalid_buffer);
475 assert!(result.is_err());
476 }
477
478 #[test]
481 fn test_accumulator_update_data_serde() {
482 use serde::Serialize;
483 let empty_update = AccumulatorUpdateData::new(Proof::WormholeMerkle {
485 vaa: PrefixedVec::from(vec![]),
486 updates: vec![],
487 });
488 let mut buffer = Vec::new();
489 let mut cursor = std::io::Cursor::new(&mut buffer);
490 let mut serializer: Serializer<_, byteorder::LE> = Serializer::new(&mut cursor);
491 empty_update.serialize(&mut serializer).unwrap();
492
493 let deserialized_update = AccumulatorUpdateData::try_from_slice(&buffer).unwrap();
495
496 assert_eq!(deserialized_update, empty_update);
498 }
499
500 #[test]
502 fn test_accumulator_forward_compatibility() {
503 use serde::Serialize;
504 let empty_update = AccumulatorUpdateData::new(Proof::WormholeMerkle {
507 vaa: PrefixedVec::from(vec![]),
508 updates: vec![],
509 });
510 let mut buffer = Vec::new();
511 let mut cursor = std::io::Cursor::new(&mut buffer);
512 let mut serializer: Serializer<_, byteorder::LE> = Serializer::new(&mut cursor);
513 empty_update.serialize(&mut serializer).unwrap();
514
515 buffer[5] = 0x03;
517 AccumulatorUpdateData::try_from_slice(&buffer).unwrap();
518
519 buffer[4] = 0x03;
521 AccumulatorUpdateData::try_from_slice(&buffer).unwrap_err();
522 }
523}