xavax_avalanche/evm_atomic/
tx_format_impl.rs1use std::borrow::Borrow;
2
3use super::tx_format::*;
4use crate::avm::tx_format::{Credential, TransferableInput, TransferableOutput};
5use crate::encoding::cb58::encode_cb58;
6use crate::parser::parser_traits::Parser;
7use crate::parser::byte_conversion::*;
8
9
10impl Parser for EVMOutput {
16 fn from_bytes(&mut self, raw_payload: &[u8], offset: Option<&mut usize>) {
17 let mut offset: usize = 0;
18 self.address.address_bytes = raw_payload[offset..=(offset + 19)].try_into().expect("Slice with incorrect length! diinki pls fix");
19 offset += 20;
20 self.amount = extract_u64(raw_payload[offset..=(offset + 7)].borrow());
21 offset += 8;
22 self.asset_id = raw_payload[offset..=(offset + 31)].try_into().expect("Slice with incorrect length! diinki pls fix");
23 }
24
25 fn to_bytes(&self) -> Vec<u8> {
26 let mut result: Vec<u8> = Vec::new();
27 result.extend_from_slice(&self.address.address_bytes);
28 result.extend_from_slice(&self.amount.to_be_bytes());
29 result.extend_from_slice(&self.asset_id);
30 result
31 }
32
33 fn to_cb58(&self) -> String {
34 encode_cb58(&self.to_bytes()[..])
35 }
36}
37impl Parser for EVMInput {
38 fn from_bytes(&mut self, raw_payload: &[u8], offset: Option<&mut usize>) {
39 let mut offset: usize = 0;
40 self.address.address_bytes = raw_payload[offset..=(offset + 19)].try_into().expect("Slice with incorrect length! diinki pls fix");
41 offset += 20;
42 self.amount = extract_u64(raw_payload[offset..=(offset + 7)].borrow());
43 offset += 8;
44 self.asset_id = raw_payload[offset..=(offset + 31)].try_into().expect("Slice with incorrect length! diinki pls fix");
45 offset += 32;
46 self.nonce = extract_u64(raw_payload[offset..=(offset + 7)].borrow());
47 }
48
49 fn to_bytes(&self) -> Vec<u8> {
50 let mut result: Vec<u8> = Vec::new();
51 result.extend_from_slice(&self.address.address_bytes);
52 result.extend_from_slice(&self.amount.to_be_bytes());
53 result.extend_from_slice(&self.asset_id);
54 result.extend_from_slice(&self.nonce.to_be_bytes());
55 result
56 }
57
58 fn to_cb58(&self) -> String {
59 encode_cb58(&self.to_bytes()[..])
60 }
61}
62
63impl Parser for ExportTx {
64 fn from_bytes(&mut self, raw_payload: &[u8], offset: Option<&mut usize>) {
65 let mut offset: usize = 0;
66 self.type_id = extract_u32(raw_payload[offset..=(offset + 3)].borrow());
67 offset += 4;
68 self.network_id = extract_u32(raw_payload[offset..=(offset + 3)].borrow());
69 offset += 4;
70 self.blockchain_id = raw_payload[offset..=(offset + 31)].try_into().expect("Incorrect slice length!");
71 offset += 32;
72 self.destination_chain = raw_payload[offset..=(offset + 31)].try_into().expect("Incorrect slice length!");
73 offset += 32;
74
75 let inputs_len: u32 = extract_u32(raw_payload[offset..=(offset + 3)].borrow());
76 offset += 4;
77
78 let mut index: usize = 0;
79 while index < inputs_len as usize {
80 let mut input: EVMInput = EVMInput::default();
81 input.from_bytes(&raw_payload[offset..], None);
82 self.inputs.push(input.clone());
83 offset += input.to_bytes().len();
84 index += 1;
85 }
86
87 let output_len: u32 = extract_u32(raw_payload[offset..=(offset + 3)].borrow());
88 offset += 4;
89
90 let mut index: usize = 0;
91 while index < output_len as usize {
92 let mut output: TransferableOutput = TransferableOutput::default();
93 output.from_bytes(&raw_payload[offset..], None);
94 self.exported_outputs.push(output.clone());
95 offset += output.to_bytes().len();
96 index += 1;
97 }
98 }
99
100 fn to_bytes(&self) -> Vec<u8> {
101 let mut result: Vec<u8> = Vec::new();
102 result.extend_from_slice(&self.type_id.to_be_bytes());
103 result.extend_from_slice(&self.network_id.to_be_bytes());
104 result.extend_from_slice(&self.blockchain_id);
105 result.extend_from_slice(&self.destination_chain);
106
107 result.extend_from_slice(&(self.inputs.len() as u32).to_be_bytes());
108 for i in &self.inputs {
109 result.extend_from_slice(&i.to_bytes()[..]);
110 }
111
112 result.extend_from_slice(&(self.exported_outputs.len() as u32).to_be_bytes());
113 for t_o in &self.exported_outputs {
114 result.extend_from_slice(&t_o.to_bytes()[..]);
115 }
116 result
117 }
118
119 fn to_cb58(&self) -> String {
120 encode_cb58(&self.to_bytes()[..])
121 }
122}
123
124impl Parser for ImportTx {
125 fn from_bytes(&mut self, raw_payload: &[u8], offset: Option<&mut usize>) {
126 let mut offset: usize = 0;
127 self.type_id = extract_u32(raw_payload[offset..=(offset + 3)].borrow());
128 offset += 4;
129 self.network_id = extract_u32(raw_payload[offset..=(offset + 3)].borrow());
130 offset += 4;
131 self.blockchain_id = raw_payload[offset..=(offset + 31)].try_into().expect("Incorrect slice length!");
132 offset += 32;
133 self.source_chain = raw_payload[offset..=(offset + 31)].try_into().expect("Incorrect slice length!");
134 offset += 32;
135
136 let input_len: u32 = extract_u32(raw_payload[offset..=(offset + 3)].borrow());
137 offset += 4;
138
139 let mut index: usize = 0;
140 while index < input_len as usize {
141 let mut input: TransferableInput = TransferableInput::default();
142 input.from_bytes(&raw_payload[offset..], None);
143 self.imported_inputs.push(input.clone());
144 offset += input.to_bytes().len();
145 index += 1;
146 }
147
148 let imported_inputs_len: u32 = extract_u32(raw_payload[offset..=(offset + 3)].borrow());
149 offset += 4;
150
151 let mut index: usize = 0;
152 while index < imported_inputs_len as usize {
153 let mut output: EVMOutput = EVMOutput::default();
154 output.from_bytes(&raw_payload[offset..], None);
155 self.outputs.push(output.clone());
156 offset += output.to_bytes().len();
157 index += 1;
158 }
159 }
160
161 fn to_bytes(&self) -> Vec<u8> {
162 let mut result: Vec<u8> = Vec::new();
163 result.extend_from_slice(&self.type_id.to_be_bytes());
164 result.extend_from_slice(&self.network_id.to_be_bytes());
165 result.extend_from_slice(&self.blockchain_id);
166 result.extend_from_slice(&self.source_chain);
167
168 result.extend_from_slice(&(self.imported_inputs.len() as u32).to_be_bytes());
169 for i in &self.imported_inputs {
170 result.extend_from_slice(&i.to_bytes()[..]);
171 }
172
173 result.extend_from_slice(&(self.outputs.len() as u32).to_be_bytes());
174 for o in &self.outputs {
175 result.extend_from_slice(&o.to_bytes()[..]);
176 }
177 result
178 }
179
180 fn to_cb58(&self) -> String {
181 encode_cb58(&self.to_bytes()[..])
182 }
183}
184
185
186impl Parser for SignedTransaction {
187 fn from_bytes(&mut self, raw_payload: &[u8], offset: Option<&mut usize>) {
188 let mut offset: usize = 0;
189 self.codec_id = extract_u16(raw_payload[offset..=(offset + 1)].borrow());
190 offset += 2;
191
192 let tx_type_id: u32 = extract_u32(raw_payload[offset..=(offset + 3)].borrow());
193 match tx_type_id {
194 0 => {
195 let mut tx: ImportTx = ImportTx::default();
196 tx.from_bytes(&raw_payload[offset..], None);
197 self.atomic_tx = AtomicTx::ImportTx(tx.clone());
198 offset += tx.to_bytes().len();
199 }
200 1 => {
201 let mut tx: ExportTx = ExportTx::default();
202 tx.from_bytes(&raw_payload[offset..], None);
203 self.atomic_tx = AtomicTx::ExportTx(tx.clone());
204 offset += tx.to_bytes().len();
205 }
206 _=> {
207 panic!("Incorrect tx_id!")
208 }
209 }
210 let cred_len: u32 = extract_u32(raw_payload[offset..=(offset + 3)].borrow());
211 offset += 4;
212
213 let mut index: u32 = 0;
214 while index < cred_len {
215 let mut c = Credential::default();
216 c.from_bytes(&raw_payload[offset..], None);
217 self.credentials.push(c.clone());
218 offset += c.to_bytes().len();
219
220 index += 1;
221 }
222
223 }
224 fn to_bytes(&self) -> Vec<u8> {
225 let mut result: Vec<u8> = Vec::new();
226
227 result.extend_from_slice(&self.codec_id.to_be_bytes());
228 match &self.atomic_tx {
229 AtomicTx::ImportTx(tx) => {
230 result.extend_from_slice(&tx.to_bytes()[..]);
231 },
232 AtomicTx::ExportTx(tx) => {
233 result.extend_from_slice(&tx.to_bytes()[..]);
234 },
235 }
236
237 result.extend_from_slice(&(self.credentials.len() as u32).to_be_bytes());
238 for i in &self.credentials {
239 result.extend_from_slice(&i.to_bytes());
240 }
241 result
242 }
243 fn to_cb58(&self) -> String {
244 encode_cb58(&self.to_bytes()[..])
245 }
246}
247
248
249#[cfg(test)]
250mod tests {
251 use crate::encoding::cb58::decode_cb58;
252 use crate::evm_atomic::tx_format::*;
253 use crate::parser::parser_traits::Parser;
254
255
256 #[test]
261 fn test_signed_transactions() {
262
263 let cb_58_encoded_tx = "111111111879MAjcAYPQY7BPt8JDK9oJrKf88WfnUdX7dPpKTZRb9MxnwzRmG9MiCPndDfJMKpU3xjSLoboA15Y1no9J3vdc9YV3WAVmamjDMGYxffQ3jBsEB2yUEa5mvhwkAHpZMtnWRvnU3EimZY377FCCFfvAc3RVesPJoe5cuZTjAk1MH3hz23xXeURUYSEBWHsNd4ByxLFNejRtRyV9AN3bmWTrWN4F6fXvKwd1uicCw5FSjJUfQDZpBD84htGu4q7KUCXHBT4ze3caembBiJ1BMHRgG4Wa4kvfaWwrBpBMvv3eKxWoHgja4pJ8jckq64N8wCEt3bS5xBZrBbrsg7xCmr6vHG7P95ahepcQDGwu9ANCWfyxeoBCHTeXiHDzR9PAXk4fzuRZ4J196k1i6NDrZxHm9ohRa".to_string();
265 let temp = decode_cb58(cb_58_encoded_tx.clone());
266
267 let mut tx: SignedTransaction = SignedTransaction::default();
268 tx.from_bytes(&temp, None);
269
270 assert_eq!(tx.to_cb58(), cb_58_encoded_tx);
271
272 let cb_58_encoded_tx = "111119TRcmX2yWov6MZAQjGpUwLsrQkofTZg9FjNiX2vryYzsKbvwVu8EVobeZ9NqJo9AcYDrLiB8u1QQduF7Gpu6ktiij117A5PNjRinDMMm77VDaT7ZG8CFEjNSQT3TiQ28eyBZ5rWKsTd74phC6zS7TRZtqXecsie5sgUxF5hSZfPNMcZpTpRPtvauuFx6F85bpV8HPBfEXzZYafczqGn1S8SzCKa5QodPsR9y5KX25rYb2xbBVLDeRA8fV2NPyxHwA6kKbJ7vNdyV9w4Gv1NAT5HRRVrPoDC2SE3SPAzytVmSUPgjwLaq3zUQ1iD6z8hER9E9idGT2dbvdyWx2YiC46YFH1R4wkx6kEWZURSKc54vqv9y13pe5tyYJFRuZ3wqWiPV7qcpq1M1GfyZUubjY8323TcATRjNJ".to_string();
274 let temp = decode_cb58(cb_58_encoded_tx.clone());
275
276 let mut tx: SignedTransaction = SignedTransaction::default();
277 tx.from_bytes(&temp, None);
278
279 assert_eq!(tx.to_cb58(), cb_58_encoded_tx);
280 }
281}