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