1use {
2 self::format_magics_le::{EVM_FORMAT_MAGIC, SOLANA_FORMAT_MAGIC},
3 crate::router::ParsedPayload,
4 anyhow::{bail, Context},
5 byteorder::{ByteOrder, ReadBytesExt, WriteBytesExt, BE, LE},
6 derive_more::From,
7 format_magics_le::{JSON_FORMAT_MAGIC, LE_ECDSA_FORMAT_MAGIC, LE_UNSIGNED_FORMAT_MAGIC},
8 std::io::{Cursor, Read, Write},
9};
10
11pub mod format_magics_le {
13 pub const JSON_FORMAT_MAGIC: u32 = 3302625434;
20 pub const EVM_FORMAT_MAGIC: u32 = 2593727018;
22 pub const SOLANA_FORMAT_MAGIC: u32 = 2182742457;
25 pub const LE_ECDSA_FORMAT_MAGIC: u32 = 1296547300;
28 pub const LE_UNSIGNED_FORMAT_MAGIC: u32 = 1499680012;
31}
32
33#[derive(Debug, Clone, PartialEq, Eq, Hash, From)]
34pub enum Message {
35 Evm(EvmMessage),
36 Solana(SolanaMessage),
37 LeEcdsa(LeEcdsaMessage),
38 LeUnsigned(LeUnsignedMessage),
39 Json(ParsedPayload),
40}
41
42impl Message {
43 pub fn serialize(&self, mut writer: impl Write) -> anyhow::Result<()> {
44 match self {
45 Message::Evm(message) => message.serialize(writer),
46 Message::Solana(message) => message.serialize(writer),
47 Message::LeEcdsa(message) => message.serialize(writer),
48 Message::LeUnsigned(message) => message.serialize(writer),
49 Message::Json(message) => {
50 writer.write_u32::<LE>(JSON_FORMAT_MAGIC)?;
51 serde_json::to_writer(writer, message)?;
52 Ok(())
53 }
54 }
55 }
56
57 pub fn deserialize_slice(data: &[u8]) -> anyhow::Result<Self> {
58 let magic = LE::read_u32(data.get(0..4).context("data too short")?);
59 match magic {
60 JSON_FORMAT_MAGIC => Ok(serde_json::from_slice::<ParsedPayload>(&data[4..])?.into()),
61 EVM_FORMAT_MAGIC => Ok(EvmMessage::deserialize_slice(data)?.into()),
62 SOLANA_FORMAT_MAGIC => Ok(SolanaMessage::deserialize_slice(data)?.into()),
63 LE_ECDSA_FORMAT_MAGIC => Ok(LeEcdsaMessage::deserialize_slice(data)?.into()),
64 LE_UNSIGNED_FORMAT_MAGIC => Ok(LeUnsignedMessage::deserialize_slice(data)?.into()),
65 _ => bail!("unrecognized format magic"),
66 }
67 }
68}
69
70#[derive(Debug, Clone, PartialEq, Eq, Hash)]
72pub struct EvmMessage {
73 pub payload: Vec<u8>,
74 pub signature: [u8; 64],
75 pub recovery_id: u8,
76}
77
78impl EvmMessage {
79 pub fn serialize(&self, mut writer: impl Write) -> anyhow::Result<()> {
80 writer.write_u32::<LE>(EVM_FORMAT_MAGIC)?;
81 writer.write_all(&self.signature)?;
82 writer.write_u8(self.recovery_id)?;
83 writer.write_u16::<BE>(self.payload.len().try_into()?)?;
84 writer.write_all(&self.payload)?;
85 Ok(())
86 }
87
88 pub fn deserialize_slice(data: &[u8]) -> anyhow::Result<Self> {
89 Self::deserialize(Cursor::new(data))
90 }
91
92 pub fn deserialize(mut reader: impl Read) -> anyhow::Result<Self> {
93 let magic = reader.read_u32::<LE>()?;
94 if magic != EVM_FORMAT_MAGIC {
95 bail!("magic mismatch");
96 }
97 let mut signature = [0u8; 64];
98 reader.read_exact(&mut signature)?;
99 let recovery_id = reader.read_u8()?;
100 let payload_len: usize = reader.read_u16::<BE>()?.into();
101 let mut payload = vec![0u8; payload_len];
102 reader.read_exact(&mut payload)?;
103 Ok(Self {
104 payload,
105 signature,
106 recovery_id,
107 })
108 }
109}
110
111#[derive(Debug, Clone, PartialEq, Eq, Hash)]
113pub struct SolanaMessage {
114 pub payload: Vec<u8>,
115 pub signature: [u8; 64],
116 pub public_key: [u8; 32],
117}
118
119impl SolanaMessage {
120 pub fn serialize(&self, mut writer: impl Write) -> anyhow::Result<()> {
121 writer.write_u32::<LE>(SOLANA_FORMAT_MAGIC)?;
122 writer.write_all(&self.signature)?;
123 writer.write_all(&self.public_key)?;
124 writer.write_u16::<LE>(self.payload.len().try_into()?)?;
125 writer.write_all(&self.payload)?;
126 Ok(())
127 }
128
129 pub fn deserialize_slice(data: &[u8]) -> anyhow::Result<Self> {
130 Self::deserialize(Cursor::new(data))
131 }
132
133 pub fn deserialize(mut reader: impl Read) -> anyhow::Result<Self> {
134 let magic = reader.read_u32::<LE>()?;
135 if magic != SOLANA_FORMAT_MAGIC {
136 bail!("magic mismatch");
137 }
138 let mut signature = [0u8; 64];
139 reader.read_exact(&mut signature)?;
140 let mut public_key = [0u8; 32];
141 reader.read_exact(&mut public_key)?;
142 let payload_len: usize = reader.read_u16::<LE>()?.into();
143 let mut payload = vec![0u8; payload_len];
144 reader.read_exact(&mut payload)?;
145 Ok(Self {
146 payload,
147 signature,
148 public_key,
149 })
150 }
151}
152
153#[derive(Debug, Clone, PartialEq, Eq, Hash)]
155pub struct LeEcdsaMessage {
156 pub payload: Vec<u8>,
157 pub signature: [u8; 64],
158 pub recovery_id: u8,
159}
160
161impl LeEcdsaMessage {
162 pub fn serialize(&self, mut writer: impl Write) -> anyhow::Result<()> {
163 writer.write_u32::<LE>(LE_ECDSA_FORMAT_MAGIC)?;
164 writer.write_all(&self.signature)?;
165 writer.write_u8(self.recovery_id)?;
166 writer.write_u16::<LE>(self.payload.len().try_into()?)?;
167 writer.write_all(&self.payload)?;
168 Ok(())
169 }
170
171 pub fn deserialize_slice(data: &[u8]) -> anyhow::Result<Self> {
172 Self::deserialize(Cursor::new(data))
173 }
174
175 pub fn deserialize(mut reader: impl Read) -> anyhow::Result<Self> {
176 let magic = reader.read_u32::<LE>()?;
177 if magic != LE_ECDSA_FORMAT_MAGIC {
178 bail!("magic mismatch");
179 }
180 let mut signature = [0u8; 64];
181 reader.read_exact(&mut signature)?;
182 let recovery_id = reader.read_u8()?;
183 let payload_len: usize = reader.read_u16::<LE>()?.into();
184 let mut payload = vec![0u8; payload_len];
185 reader.read_exact(&mut payload)?;
186 Ok(Self {
187 payload,
188 signature,
189 recovery_id,
190 })
191 }
192}
193
194#[derive(Debug, Clone, PartialEq, Eq, Hash)]
196pub struct LeUnsignedMessage {
197 pub payload: Vec<u8>,
198}
199
200impl LeUnsignedMessage {
201 pub fn serialize(&self, mut writer: impl Write) -> anyhow::Result<()> {
202 writer.write_u32::<LE>(LE_UNSIGNED_FORMAT_MAGIC)?;
203 writer.write_u16::<LE>(self.payload.len().try_into()?)?;
204 writer.write_all(&self.payload)?;
205 Ok(())
206 }
207
208 pub fn deserialize_slice(data: &[u8]) -> anyhow::Result<Self> {
209 Self::deserialize(Cursor::new(data))
210 }
211
212 pub fn deserialize(mut reader: impl Read) -> anyhow::Result<Self> {
213 let magic = reader.read_u32::<LE>()?;
214 if magic != LE_UNSIGNED_FORMAT_MAGIC {
215 bail!("magic mismatch");
216 }
217 let payload_len: usize = reader.read_u16::<LE>()?.into();
218 let mut payload = vec![0u8; payload_len];
219 reader.read_exact(&mut payload)?;
220 Ok(Self { payload })
221 }
222}
223
224#[test]
225fn test_evm_serde() {
226 let m1 = EvmMessage {
227 payload: vec![1, 2, 4, 3],
228 signature: [5; 64],
229 recovery_id: 1,
230 };
231 let mut buf = Vec::new();
232 m1.serialize(&mut buf).unwrap();
233 assert_eq!(m1, EvmMessage::deserialize_slice(&buf).unwrap());
234}
235
236#[test]
237fn test_solana_serde() {
238 let m1 = SolanaMessage {
239 payload: vec![1, 2, 4, 3],
240 signature: [5; 64],
241 public_key: [6; 32],
242 };
243 let mut buf = Vec::new();
244 m1.serialize(&mut buf).unwrap();
245 assert_eq!(m1, SolanaMessage::deserialize_slice(&buf).unwrap());
246}
247
248#[test]
249fn test_le_ecdsa_serde() {
250 let m1 = LeEcdsaMessage {
251 payload: vec![1, 2, 4, 3],
252 signature: [5; 64],
253 recovery_id: 1,
254 };
255 let mut buf = Vec::new();
256 m1.serialize(&mut buf).unwrap();
257 assert_eq!(m1, LeEcdsaMessage::deserialize_slice(&buf).unwrap());
258}
259
260#[test]
261fn test_le_unsigned_serde() {
262 let m1 = LeUnsignedMessage {
263 payload: vec![1, 2, 4, 3],
264 };
265 let mut buf = Vec::new();
266 m1.serialize(&mut buf).unwrap();
267 assert_eq!(m1, LeUnsignedMessage::deserialize_slice(&buf).unwrap());
268}