pyth_lazer_protocol/
message.rs

1use {
2    crate::payload::{EVM_FORMAT_MAGIC, SOLANA_FORMAT_MAGIC_LE},
3    anyhow::bail,
4    byteorder::{ReadBytesExt, WriteBytesExt, BE, LE},
5    std::io::{Cursor, Read, Write},
6};
7
8/// EVM signature enveope.
9#[derive(Debug, Clone, PartialEq, Eq, Hash)]
10pub struct EvmMessage {
11    pub payload: Vec<u8>,
12    pub signature: [u8; 64],
13    pub recovery_id: u8,
14}
15
16impl EvmMessage {
17    pub fn serialize(&self, mut writer: impl Write) -> anyhow::Result<()> {
18        writer.write_u32::<BE>(EVM_FORMAT_MAGIC)?;
19        writer.write_all(&self.signature)?;
20        writer.write_u8(self.recovery_id)?;
21        writer.write_u16::<BE>(self.payload.len().try_into()?)?;
22        writer.write_all(&self.payload)?;
23        Ok(())
24    }
25
26    pub fn deserialize_slice(data: &[u8]) -> anyhow::Result<Self> {
27        Self::deserialize(Cursor::new(data))
28    }
29
30    pub fn deserialize(mut reader: impl Read) -> anyhow::Result<Self> {
31        let magic = reader.read_u32::<BE>()?;
32        if magic != EVM_FORMAT_MAGIC {
33            bail!("magic mismatch");
34        }
35        let mut signature = [0u8; 64];
36        reader.read_exact(&mut signature)?;
37        let recovery_id = reader.read_u8()?;
38        let payload_len: usize = reader.read_u16::<BE>()?.into();
39        let mut payload = vec![0u8; payload_len];
40        reader.read_exact(&mut payload)?;
41        Ok(Self {
42            payload,
43            signature,
44            recovery_id,
45        })
46    }
47}
48
49/// Solana signature envelope.
50#[derive(Debug, Clone, PartialEq, Eq, Hash)]
51pub struct SolanaMessage {
52    pub payload: Vec<u8>,
53    pub signature: [u8; 64],
54    pub public_key: [u8; 32],
55}
56
57impl SolanaMessage {
58    pub fn serialize(&self, mut writer: impl Write) -> anyhow::Result<()> {
59        writer.write_u32::<LE>(SOLANA_FORMAT_MAGIC_LE)?;
60        writer.write_all(&self.signature)?;
61        writer.write_all(&self.public_key)?;
62        writer.write_u16::<LE>(self.payload.len().try_into()?)?;
63        writer.write_all(&self.payload)?;
64        Ok(())
65    }
66
67    pub fn deserialize_slice(data: &[u8]) -> anyhow::Result<Self> {
68        Self::deserialize(Cursor::new(data))
69    }
70
71    pub fn deserialize(mut reader: impl Read) -> anyhow::Result<Self> {
72        let magic = reader.read_u32::<LE>()?;
73        if magic != SOLANA_FORMAT_MAGIC_LE {
74            bail!("magic mismatch");
75        }
76        let mut signature = [0u8; 64];
77        reader.read_exact(&mut signature)?;
78        let mut public_key = [0u8; 32];
79        reader.read_exact(&mut public_key)?;
80        let payload_len: usize = reader.read_u16::<LE>()?.into();
81        let mut payload = vec![0u8; payload_len];
82        reader.read_exact(&mut payload)?;
83        Ok(Self {
84            payload,
85            signature,
86            public_key,
87        })
88    }
89}
90
91#[test]
92fn test_evm_serde() {
93    let m1 = EvmMessage {
94        payload: vec![1, 2, 4, 3],
95        signature: [5; 64],
96        recovery_id: 1,
97    };
98    let mut buf = Vec::new();
99    m1.serialize(&mut buf).unwrap();
100    assert_eq!(m1, EvmMessage::deserialize_slice(&buf).unwrap());
101}
102
103#[test]
104fn test_solana_serde() {
105    let m1 = SolanaMessage {
106        payload: vec![1, 2, 4, 3],
107        signature: [5; 64],
108        public_key: [6; 32],
109    };
110    let mut buf = Vec::new();
111    m1.serialize(&mut buf).unwrap();
112    assert_eq!(m1, SolanaMessage::deserialize_slice(&buf).unwrap());
113}