1use crate::*;
2use base64::{engine::general_purpose::STANDARD as b64, Engine as _};
3use hex::FromHex;
4use serde::{Deserialize, Serialize};
5use sha3::{Digest, Keccak256};
6use std::str::FromStr;
7
8#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
14pub struct EvmTransaction {
15 pub expiration_time_seconds: u64,
17 pub gas_limit: String,
19 pub value: String,
21 pub to: Vec<u8>,
23 pub from: Vec<u8>,
25 pub data: Vec<u8>,
27}
28
29#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
30pub struct EvmFunctionResultV0 {
31 pub txs: Vec<EvmTransaction>,
33 pub signatures: Vec<Vec<u8>>,
34
35 pub call_ids: Vec<Vec<u8>>,
38 pub checksums: Vec<Vec<u8>>,
39}
40
41#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
42pub struct EvmFunctionResultV1 {
43 pub function_id: String,
45
46 pub signer: String,
48
49 pub txs: Vec<EvmTransaction>,
50
51 pub signatures: Vec<String>,
52
53 pub resolved_ids: Vec<String>,
55
56 pub checksums: Vec<String>,
58
59 pub error_codes: Vec<u8>,
61}
62
63impl EvmFunctionResultV1 {
64 pub fn hash(&self) -> Vec<u8> {
66 let mut buffer = Vec::new();
67
68 buffer.extend(self.function_id.as_bytes());
69
70 buffer.extend(self.signer.as_bytes());
71
72 for tx in &self.txs {
73 buffer.extend(&tx.expiration_time_seconds.to_le_bytes());
74 buffer.extend(tx.gas_limit.as_bytes());
75 buffer.extend(tx.value.as_bytes());
76 buffer.extend(&tx.to);
77 buffer.extend(&tx.from);
78 buffer.extend(&tx.data);
79 }
80
81 for signature in &self.signatures {
82 buffer.extend(signature.as_bytes());
83 }
84
85 for resolved_id in &self.resolved_ids {
86 buffer.extend(resolved_id.as_bytes());
87 }
88
89 for checksum in &self.checksums {
90 buffer.extend(checksum.as_bytes());
91 }
92
93 buffer.extend(&self.error_codes);
94
95 let mut hasher = Keccak256::new();
96 hasher.update(buffer);
97 hasher.finalize().to_vec()
98 }
99}
100
101#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
103#[serde(tag = "version")]
104pub enum EvmFunctionResult {
105 V0(EvmFunctionResultV0),
106 V1(EvmFunctionResultV1),
107}
108impl Default for EvmFunctionResult {
109 fn default() -> Self {
110 Self::V0(EvmFunctionResultV0::default())
111 }
112}
113#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
114pub struct LegacyEvmFunctionResult {
115 pub txs: Vec<EvmTransaction>,
117 pub signatures: Vec<Vec<u8>>,
118
119 pub call_ids: Vec<Vec<u8>>,
122 pub checksums: Vec<Vec<u8>>,
123}
124impl From<LegacyEvmFunctionResult> for EvmFunctionResult {
125 fn from(item: LegacyEvmFunctionResult) -> EvmFunctionResult {
126 EvmFunctionResult::V0(EvmFunctionResultV0 {
127 txs: item.txs,
128 signatures: item.signatures,
129 call_ids: item.call_ids,
130 checksums: item.checksums,
131 })
132 }
133}
134#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
141pub struct SolanaFunctionResultV0 {
142 pub serialized_tx: Vec<u8>,
144}
145
146#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
147pub enum SolanaFunctionRequestType {
148 Routine(Vec<u8>),
149 Request(Vec<u8>),
150 Function(Vec<u8>),
152}
153impl Default for SolanaFunctionRequestType {
154 fn default() -> Self {
155 Self::Function(vec![])
156 }
157}
158impl SolanaFunctionRequestType {
159 pub fn is_routine(&self) -> bool {
160 matches!(self, SolanaFunctionRequestType::Routine(_))
161 }
162
163 pub fn is_request(&self) -> bool {
164 matches!(self, SolanaFunctionRequestType::Request(_))
165 }
166}
167
168#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
170pub struct SolanaFunctionResultV1 {
171 pub fn_key: Vec<u8>,
172 pub serialized_tx: Vec<u8>,
174 pub request_type: SolanaFunctionRequestType,
176 pub request_hash: Vec<u8>,
178}
179
180#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
181#[serde(tag = "version")]
182pub enum SolanaFunctionResult {
183 V0(SolanaFunctionResultV0),
184 V1(SolanaFunctionResultV1),
185}
186impl Default for SolanaFunctionResult {
187 fn default() -> Self {
188 Self::V1(SolanaFunctionResultV1::default())
189 }
190}
191impl SolanaFunctionResult {
192 pub fn serialized_tx(&self) -> Vec<u8> {
193 match self {
194 SolanaFunctionResult::V0(SolanaFunctionResultV0 { serialized_tx }) => {
195 serialized_tx.clone()
196 }
197 SolanaFunctionResult::V1(SolanaFunctionResultV1 { serialized_tx, .. }) => {
198 serialized_tx.clone()
199 }
200 }
201 }
202}
203
204#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
209pub enum StarknetFunctionRequestType {
210 Routine(Vec<u8>),
211 Request(Vec<u8>),
212}
213impl Default for StarknetFunctionRequestType {
214 fn default() -> Self {
215 Self::Routine(vec![])
216 }
217}
218impl StarknetFunctionRequestType {
219 pub fn is_routine(&self) -> bool {
220 matches!(self, StarknetFunctionRequestType::Routine(_))
221 }
222
223 pub fn is_request(&self) -> bool {
224 matches!(self, StarknetFunctionRequestType::Request(_))
225 }
226}
227
228#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
229pub struct StarknetCall {
230 pub to: Vec<u8>,
231 pub selector: Vec<u8>,
232 pub calldata: Vec<Vec<u8>>,
233}
234
235#[derive(Default, Clone, PartialEq, Debug, Serialize, Deserialize)]
236pub struct StarknetFunctionResultV0 {
237 pub function_id: Vec<u8>,
238 pub function_request_id: Vec<u8>,
239 pub txs: Vec<StarknetCall>,
240 pub request_type: StarknetFunctionRequestType,
241}
242
243#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
244#[serde(tag = "version")]
245pub enum StarknetFunctionResult {
246 V0(StarknetFunctionResultV0),
247}
248impl Default for StarknetFunctionResult {
249 fn default() -> Self {
250 Self::V0(StarknetFunctionResultV0::default())
251 }
252}
253
254#[derive(Default, PartialEq, Clone, Debug, Serialize, Deserialize)]
259#[serde(tag = "chain")]
260pub enum ChainResultInfo {
261 #[default]
262 None,
263 Solana(SolanaFunctionResult),
264 Evm(EvmFunctionResult),
265 Starknet(StarknetFunctionResult),
266}
267
268#[derive(Clone, PartialEq, Default, Debug, Serialize, Deserialize)]
270pub struct FunctionResultV0 {
271 pub quote: Vec<u8>,
273 pub fn_key: Vec<u8>,
275 pub signer: Vec<u8>,
277 pub fn_request_key: Vec<u8>,
279 pub fn_request_hash: Vec<u8>,
281 pub chain_result_info: ChainResultInfo,
283 #[serde(default)]
286 pub error_code: u8,
287}
288
289#[derive(Clone, PartialEq, Default, Debug, Serialize, Deserialize)]
291pub struct FunctionResultV1 {
292 pub quote: Vec<u8>,
294 pub signer: Vec<u8>,
296 pub signature: Vec<u8>,
298 pub chain_result_info: ChainResultInfo,
300 #[serde(default)]
302 pub error_code: u8,
303}
304
305#[derive(Clone, PartialEq, Debug, Serialize, Deserialize)]
306#[serde(tag = "version")]
307pub enum FunctionResult {
308 V0(FunctionResultV0),
309 V1(FunctionResultV1),
310}
311impl Default for FunctionResult {
312 fn default() -> Self {
313 Self::V1(FunctionResultV1::default())
314 }
315}
316
317pub static FUNCTION_RESULT_PREFIX: &str = "FN_OUT: ";
318
319impl FunctionResult {
320 pub fn is_solana(&self) -> bool {
321 match self {
322 FunctionResult::V0(FunctionResultV0 {
323 chain_result_info, ..
324 }) => matches!(chain_result_info, ChainResultInfo::Solana(_)),
325 FunctionResult::V1(FunctionResultV1 {
326 chain_result_info, ..
327 }) => matches!(chain_result_info, ChainResultInfo::Solana(_)),
328 }
329 }
330
331 pub fn is_evm(&self) -> bool {
332 match self {
333 FunctionResult::V0(FunctionResultV0 {
334 chain_result_info, ..
335 }) => matches!(chain_result_info, ChainResultInfo::Evm(_)),
336 FunctionResult::V1(FunctionResultV1 {
337 chain_result_info, ..
338 }) => matches!(chain_result_info, ChainResultInfo::Evm(_)),
339 }
340 }
341
342 pub fn is_starknet(&self) -> bool {
343 match self {
344 FunctionResult::V0(FunctionResultV0 {
345 chain_result_info, ..
346 }) => matches!(chain_result_info, ChainResultInfo::Starknet(_)),
347 FunctionResult::V1(FunctionResultV1 {
348 chain_result_info, ..
349 }) => matches!(chain_result_info, ChainResultInfo::Starknet(_)),
350 }
351 }
352
353 pub fn error_code(&self) -> u8 {
354 match self {
355 FunctionResult::V0(FunctionResultV0 { error_code, .. }) => *error_code,
356 FunctionResult::V1(FunctionResultV1 { error_code, .. }) => *error_code,
357 }
358 }
359
360 pub fn set_error_code(&mut self, error_code: u8) {
361 match self {
362 FunctionResult::V0(v) => {
363 v.error_code = error_code;
364 }
365 FunctionResult::V1(v) => {
366 v.error_code = error_code;
367 }
368 }
369 }
370
371 pub fn is_err(&self) -> bool {
372 self.error_code() != 0
373 }
374
375 pub fn version(&self) -> u32 {
376 match self {
377 FunctionResult::V0(_) => 0,
378 FunctionResult::V1(_) => 1,
379 }
380 }
381
382 pub fn fn_key(&self) -> Result<Vec<u8>, SbError> {
383 let fn_key = match self {
384 FunctionResult::V0(FunctionResultV0 { fn_key, .. }) => fn_key.clone(),
385 FunctionResult::V1(FunctionResultV1 {
386 chain_result_info, ..
387 }) => match chain_result_info {
388 ChainResultInfo::Solana(sol) => match sol {
389 SolanaFunctionResult::V0(_) => vec![],
390 SolanaFunctionResult::V1(v) => v.fn_key.clone(),
391 },
392 ChainResultInfo::Evm(evm) => match evm {
393 EvmFunctionResult::V0(_v) => vec![],
394 EvmFunctionResult::V1(v) => v.function_id.as_str().as_bytes().to_vec(),
395 },
396 ChainResultInfo::Starknet(starknet) => match starknet {
397 StarknetFunctionResult::V0(v) => v.function_id.clone(),
398 },
399 _ => vec![],
400 },
401 };
402
403 if fn_key.is_empty() {
404 Err("Failed to get fn_key from FunctionResult".into())
405 } else {
406 Ok(fn_key)
407 }
408 }
409
410 pub fn chain_result_info(&self) -> Result<ChainResultInfo, SbError> {
411 let chain_result_info = match self {
412 FunctionResult::V0(v) => v.chain_result_info.clone(),
413 FunctionResult::V1(v) => v.chain_result_info.clone(),
414 };
415
416 Ok(chain_result_info)
417 }
418
419 pub fn quote_bytes(&self) -> &[u8] {
420 match self {
421 FunctionResult::V0(FunctionResultV0 { quote, .. }) => quote,
422 FunctionResult::V1(FunctionResultV1 { quote, .. }) => quote,
423 }
424 }
425
426 cfg_client! {
427 pub fn quote(&self) -> Result<sgx_quote::Quote, SbError> {
428 sgx_quote::Quote::parse(&self.quote_bytes()).map_err(|_| SbError::QuoteParseError)
429 }
430 }
431
432 pub fn signer(&self) -> &[u8] {
433 match self {
434 FunctionResult::V0(FunctionResultV0 { signer, .. }) => signer,
435 FunctionResult::V1(FunctionResultV1 { signer, .. }) => signer,
436 }
437 }
438
439 pub fn to_string(&self) -> Result<String, SbError> {
440 serde_json::to_string(&self).map_err(|e| SbError::CustomError {
441 message: "Failed to convert FunctionResult to string".to_string(),
442 source: std::sync::Arc::new(e),
443 })
444 }
445
446 pub fn hex_encode(&self) -> String {
447 hex::encode(self.to_string().unwrap_or_default())
448 }
449
450 pub fn emit_hex(&self) {
451 println!(
452 "{}{}",
453 FUNCTION_RESULT_PREFIX,
454 hex::encode(self.to_string().unwrap())
455 );
456 }
457
458 pub fn emit_base64(&self) {
459 println!(
460 "{}{}",
461 FUNCTION_RESULT_PREFIX,
462 b64.encode(self.to_string().unwrap().as_bytes())
463 );
464 }
465
466 pub fn emit(&self) {
467 self.emit_hex()
468 }
469
470 pub fn decode(s: &str) -> std::result::Result<Self, SbError> {
471 Self::from_str(s)
472 }
473}
474impl From<LegacyFunctionResult> for FunctionResult {
475 fn from(item: LegacyFunctionResult) -> FunctionResult {
476 FunctionResult::V0(FunctionResultV0 {
477 quote: item.quote,
478 fn_key: item.fn_key,
479 signer: item.signer,
480 fn_request_key: item.fn_request_key,
481 fn_request_hash: item.fn_request_hash,
482 chain_result_info: item.chain_result_info.into(),
483 error_code: item.error_code,
484 })
485 }
486}
487impl FromHex for FunctionResult {
488 type Error = SbError;
489
490 fn from_hex<T: AsRef<[u8]>>(hex: T) -> std::result::Result<Self, Self::Error> {
492 let bytes = hex::decode(hex)?;
493
494 bytes.try_into()
495 }
496}
497impl FromStr for FunctionResult {
498 type Err = SbError;
499
500 fn from_str(s: &str) -> std::result::Result<Self, Self::Err> {
501 let s = s.strip_prefix(FUNCTION_RESULT_PREFIX).unwrap_or(s);
503
504 let bytes = match hex::decode(s) {
506 Ok(b) => b,
507 Err(_) => s.as_bytes().to_vec(),
509 };
510
511 bytes.try_into()
512 }
513}
514
515impl TryFrom<Vec<u8>> for FunctionResult {
516 type Error = SbError;
517
518 fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
519 let error_msg = match serde_json::from_slice::<FunctionResult>(&bytes) {
521 Ok(deserialized) => {
522 return Ok(deserialized);
523 }
524 Err(e) => {
525 format!("Failed to decode FunctionResult: {:?}", e)
526 }
527 };
528
529 match serde_json::from_slice::<LegacyFunctionResult>(&bytes) {
531 Ok(deserialized) => {
532 return Ok(deserialized.into());
533 }
534 Err(e) => {
535 log::info!("Failed to decode LegacyFunctionResult: {:?}", e);
536 }
537 }
538
539 println!("{}", String::from_utf8(bytes).unwrap_or_default());
540
541 Err(SbError::CustomMessage(format!(
542 "Failed to decode FunctionResult {:?}",
543 error_msg
544 )))
545 }
546}
547
548#[derive(Clone, PartialEq, Default, Debug, Serialize, Deserialize)]
551pub struct LegacyFunctionResult {
552 pub version: u32,
554 pub quote: Vec<u8>,
556 pub fn_key: Vec<u8>,
558 pub signer: Vec<u8>,
560 pub fn_request_key: Vec<u8>,
562 pub fn_request_hash: Vec<u8>,
564 pub chain_result_info: LegacyChainResultInfo,
566 #[serde(default)]
569 pub error_code: u8,
570}
571
572#[derive(Default, PartialEq, Clone, Debug, Serialize, Deserialize)]
573pub enum LegacyChainResultInfo {
574 #[default]
575 None,
576 Solana(LegacySolanaFunctionResult),
577 Evm(LegacyEvmFunctionResult),
578}
579impl From<LegacyChainResultInfo> for ChainResultInfo {
580 fn from(item: LegacyChainResultInfo) -> ChainResultInfo {
581 match item {
582 LegacyChainResultInfo::Solana(sol) => ChainResultInfo::Solana(sol.into()),
583 LegacyChainResultInfo::Evm(evm) => ChainResultInfo::Evm(evm.into()),
584 _ => ChainResultInfo::None,
585 }
586 }
587}
588
589#[derive(Default, PartialEq, Clone, Debug, Serialize, Deserialize)]
590pub struct LegacySolanaFunctionResult {
591 pub serialized_tx: Vec<u8>,
592}
593impl From<LegacySolanaFunctionResult> for SolanaFunctionResult {
594 fn from(item: LegacySolanaFunctionResult) -> SolanaFunctionResult {
595 SolanaFunctionResult::V0(SolanaFunctionResultV0 {
596 serialized_tx: item.serialized_tx,
597 })
598 }
599}
600
601#[cfg(test)]
602mod tests {
603 use super::*;
604 use pretty_assertions::assert_eq;
605 use rand::Rng;
606
607 pub const EMPTY_ENCODED_FN_RESULT: &str =
609 "7b2276657273696f6e223a302c2271756f7465223a5b5d2c22666e5f6b6579223a5b5d2c227369676e6572223a5b5d2c22666e5f726571756573745f6b6579223a5b5d2c22666e5f726571756573745f68617368223a5b5d2c22636861696e5f726573756c745f696e666f223a224e6f6e65222c226572726f725f636f6465223a307d";
610
611 pub const TEST_CASE_1: &str =
616 "FN_OUT: 7b2276657273696f6e223a312c2271756f7465223a5b332c302c322c302c302c302c302c302c392c302c31342c302c3134372c3135342c3131342c35312c3234372c3135362c37362c3136392c3134382c31302c31332c3137392c3134392c3132372c362c372c3138362c3131382c3133362c36392c342c3133382c3137362c35342c36362c3133372c3132392c3132342c32372c3138392c36362c3132322c302c302c302c302c31322c31322c31362c31352c3235352c3235352c312c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c352c302c302c302c302c302c302c302c3233312c302c302c302c302c302c302c302c32332c3235352c3135322c3234302c372c3134302c3232392c3130352c3133312c3138372c36322c3136302c31372c3230302c3137372c3135362c3233382c3231332c3234322c3135362c3135332c39342c352c37372c39312c3231382c3138332c3134362c3138312c3230362c3137332c3130382c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c3233312c3234312c3231392c3231342c3136322c3232352c32312c34362c3232372c3138372c3139342c37332c3233362c36332c39362c39362c3230392c3230332c3235312c33302c3231372c35332c36332c3232352c3231332c34302c37352c3133372c3137332c39302c3231362c3131332c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c3136382c3232362c39332c3137332c3230392c31302c37392c39302c34332c3138342c3230362c36342c33302c3230342c36352c3135382c3135332c33322c32322c33382c3234362c3235302c3231372c39312c36322c3133332c3136352c3132392c3233332c39332c3139362c34332c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c3230322c31362c302c302c3130382c32312c3136312c3234312c3233342c3233362c3130372c3235302c3134372c32332c3132332c3133382c3230342c3139332c3139392c3130312c3136372c3134322c3137312c3234372c3139302c3138372c3135302c322c3133302c3130332c3134392c3230332c3234312c38322c34392c392c3232362c3233392c35332c3132312c33312c37312c3233382c3232362c35332c3130362c33302c31392c3136342c32312c3132312c3230302c3137392c3138372c3137392c3130312c32342c3136342c3138342c3231342c3232352c3138392c3130342c3131352c3232392c3234352c3233342c38392c3231352c3134332c3137392c39332c3132382c39392c37382c3230382c3137382c3139362c3130382c3137352c36362c32342c3234302c3132362c3130382c3138372c382c3232332c3137372c3230362c3131322c31342c3234332c3133372c3234372c3130312c3136362c3139332c34382c36382c38352c3233352c3136322c3231342c32342c3235342c3232392c3135342c3233322c3130332c362c3234332c33312c3138322c37312c3132382c3130352c3230302c38372c3233302c3230312c3139362c35362c32302c3230322c3233362c3130322c3134332c382c3234382c39352c31352c31322c31322c31362c31352c3235352c3235352c312c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c32312c302c302c302c302c302c302c302c3233312c302c302c302c302c302c302c302c32352c34322c3136352c31322c3232352c3139322c3230362c3234302c36302c3230372c3133372c3233312c3138312c3137372c3130372c31332c3132312c3132302c3234352c3139342c3137372c3233372c3230372c3131392c37372c3133352c3131322c34362c3132392c38342c3231362c3139312c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c3134302c37392c38372c3131372c3231352c3135302c38302c36322c3135302c31392c3132372c3131392c3139382c3133382c3133302c3135342c302c38362c3137322c3134312c3233372c3131322c32302c31312c382c32372c392c36382c3134342c3139372c3132332c3235352c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c312c302c392c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c3132302c37392c36302c36382c34342c382c3230382c3135392c3230372c33372c36382c3134322c3131392c36332c3233332c3231322c35312c3232332c3235322c3231352c3135332c3139382c3138372c36392c3137342c312c3233312c3230332c3232322c3230342c3132352c3137332c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c3132342c37372c3234372c38342c39382c39322c36342c3133322c3233392c31382c3130352c3131322c32322c34302c3233382c38332c34352c34312c37332c3135302c3134392c3133312c342c37302c3135322c3136322c3232382c3138352c37332c35382c3231342c3135372c3230342c37302c3230332c3233362c33342c3233322c35332c3132392c3234342c31342c3235312c39332c3131362c3132302c39382c3232352c3232342c38372c3132362c3234352c362c34352c34362c3135352c36372c34332c34352c3139302c34392c3130382c35392c3230352c33322c302c302c312c322c332c342c352c362c372c382c392c31302c31312c31322c31332c31342c31352c31362c31372c31382c31392c32302c32312c32322c32332c32342c32352c32362c32372c32382c32392c33302c33312c352c302c39382c31342c302c302c34352c34352c34352c34352c34352c36362c36392c37312c37332c37382c33322c36372c36392c38322c38342c37332c37302c37332c36372c36352c38342c36392c34352c34352c34352c34352c34352c31302c37372c37332c37332c36392c35362c3130362c36372c36372c36362c37342c3130392c3130332c36352c3131392c37332c36362c36352c3130332c37332c38362c36352c37392c39392c36382c38302c36352c35312c3132312c3131352c3130312c38362c38332c39382c3131382c36352c37302c3130302c3131372c3132312c3131312c38352c3132302c37362c3131362c3130352c37342c34382c3130322c37372c36352c3131312c37312c36372c36372c3131332c37312c38332c37372c35322c35372c36362c36352c37372c36372c31302c37372c37322c36352c3132302c37332c3130362c36352c3130332c36362c3130332c37382c38362c36362c36352c37372c37372c37312c38352c3130382c3131372c3130302c37312c38362c3131352c37332c37302c37382c37322c38372c36372c36362c38312c38312c34382c3131352c3130332c38352c37312c3132302c3130342c3130302c37312c39302c3131382c39392c3130392c34382c3130332c38312c34382c36392c3132302c37312c3130362c36352c38392c36362c3130332c37382c38362c36362c36352c3131312c37372c31302c36392c38352c3130382c3131372c3130302c37312c38362c3131352c37332c36392c37382c3131382c39392c3131302c36362c3131382c39392c3130392c37302c34382c39372c38372c35372c3131372c37372c38322c38312c3131392c36392c3130332c38392c36382c38362c38312c38312c37322c36382c36352c3131362c38342c38392c38372c35332c34382c38392c38332c36362c36382c39382c37312c37302c3132312c38392c38342c36392c37362c37372c36352c3130372c37312c36352c34392c38352c36392c31302c36372c36352c3131392c36372c38312c34382c36392c3132302c36372c3132322c36352c37342c36362c3130332c37382c38362c36362c36352c38392c38342c36352c3130382c38362c38342c37372c36362c35322c38382c36382c38342c37332c3132322c37372c36382c3130332c3132312c37382c36382c37332c3132302c37382c38342c3130332c34392c37372c38362c3131312c38382c36382c38342c37372c3131392c37372c36382c3130332c3132312c37382c36382c37332c3132302c37382c38342c3130332c34392c31302c37372c38362c3131312c3131392c39392c36382c36392c3130352c37372c36372c36352c37312c36352c34392c38352c36392c36352c3131392c3131392c39302c38332c38372c35332c34382c39302c38372c3131392c3130332c38352c34382c3130302c38392c37332c37302c36362c36382c38332c3132312c36362c36382c39302c38382c37342c34382c39372c38372c39302c3131322c38392c35302c37302c34382c39302c38342c36392c39372c37372c36362c3130332c37312c36352c34392c38352c36392c31302c36372c3130332c3131392c38322c38332c38372c35332c34382c39302c38372c3131392c3130332c38312c35302c35372c3132312c39392c37312c35372c3132312c38392c38382c38322c3131322c39382c35302c35322c3132302c37302c36382c36352c38332c36362c3130332c37382c38362c36362c36352c39392c37372c36372c34392c37382c3130342c39382c3131302c38322c3130342c37332c36392c37382c3131352c38392c38382c37342c3130342c37372c38312c3131352c3131392c36372c38312c38392c36382c31302c38362c38312c38312c37332c36382c36352c37342c36382c38312c38342c36392c37362c37372c36352c3130372c37312c36352c34392c38352c36392c36362c3130342c37372c36372c38362c38362c37372c3131392c38372c38342c36352c38342c36362c3130332c39392c3131332c3130342c3130372c3130362c37392c38302c38312c37332c36362c36362c3130332c3130332c3131332c3130342c3130372c3130362c37392c38302c38312c37372c36362c36362c3131392c37382c36372c36352c36352c38312c37382c31302c3131392c38392c3130302c34382c39392c3130392c36382c38392c37352c38312c3131312c37322c37302c3130362c37372c35352c3132312c38342c3130332c35352c34372c3130332c35312c3132302c39382c3131342c36352c3131362c37312c3131302c35322c38312c35332c3131302c3130312c35302c3131392c38392c38342c3130312c3130302c38372c38352c38362c3131362c36382c3131362c3130382c38392c35322c37392c3131342c3131342c3130342c35372c35372c3131392c36382c3132302c37322c38332c3132302c35322c38352c31302c36372c38392c3131362c3130382c38382c34382c38392c38392c37322c3130352c37322c3131392c37302c3131372c38372c38312c34332c38392c3130392c34382c3131312c35322c37332c36382c36382c3130362c36372c36372c36352c3131392c3131312c3131392c37322c3131392c38392c36382c38362c38322c34382c3130362c36362c36362c3130332c3131392c37302c3131312c36352c38352c3130382c38372c35372c3130302c3132322c39382c34382c39382c35322c3130312c3130382c36352c38332c39392c3131302c38352c31302c35372c36382c38302c37392c36352c38362c39392c37362c35312c3130382c38312c3131392c39372c3131392c38392c36382c38362c38322c34382c3130322c36362c37312c38312c3131392c38392c3130362c36362c3130332c3131312c37302c35342c3130332c38382c37332c39302c39372c39372c37322c38322c34382c39392c37322c37372c35342c37362c3132312c35372c3130342c39392c37312c3130372c3131372c3130302c37322c37342c34392c39392c35312c38322c3130382c39302c37322c37382c3130382c31302c39392c3131302c39302c3131322c38392c35302c38362c3132322c37362c3130392c3130382c3131372c3130302c37312c38362c3131352c37362c3130392c37382c3131382c39382c38332c35372c3132322c39302c35312c3130332c3131382c38392c35302c38362c3132312c3130302c37312c3130382c3130392c39372c38372c37382c3130342c3130302c37312c3130382c3131382c39382c3130352c35372c35302c37372c3132312c35372c3131392c38392c35302c3131362c3130362c39392c3130392c3131392c34372c38392c35302c36392c35372c31302c39392c37312c3132302c3130342c3130302c37312c39302c3131382c39392c3130392c34382c3130392c39302c38372c35332c3130362c39382c35302c38322c3131322c39382c3130392c39392c35372c39302c37312c38362c3132312c37372c36362c34382c37312c36352c34392c38352c3130302c36382c3130332c38312c38372c36362c36362c38312c37372c3130322c38372c35302c38342c34332c35302c3131372c38342c34382c38312c37342c34382c38342c37312c38342c34392c35312c3132322c39302c38372c31302c3130312c3130372c35362c34382c37392c3130362c36352c37392c36362c3130332c37382c38362c37322c38312c35362c36362c36352c3130322c35362c36392c36362c36352c37372c36372c36362c3131352c36352c3131392c36382c36352c38392c36382c38362c38322c34382c38342c36352c38312c37322c34372c36362c36352c37332c3131392c36352c36382c36372c36372c36352c3130362c3131352c37312c36372c38332c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c31302c36352c38312c38332c36372c36352c3130352c3131392c3131392c3130332c3130332c37332c3131312c37372c36362c35322c37312c36372c3130352c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c36392c36392c36392c37332c3132302c3131342c37372c38362c3132322c3130312c35302c38392c36382c35352c36372c3132322c36352c34372c37362c3130352c38332c3130362c38342c39302c34382c3131392c3130332c3130332c37302c3130382c36362c3130332c3131312c3131332c31302c3130342c3130372c3130352c37312c34332c36392c34382c36362c36382c38312c36392c36372c37372c37332c37332c36362c38362c38342c36352c38312c36362c3130332c3131352c3131332c3130342c3130372c3130352c37312c34332c36392c34382c36362c36382c38312c36392c36372c36352c38312c37332c36362c36382c36382c36352c38312c36362c3130332c3131352c3131332c3130342c3130372c3130352c37312c34332c36392c34382c36362c36382c38312c36392c36372c36352c3130332c37332c36362c31302c36382c36382c36352c38312c36362c3130332c3131352c3131332c3130342c3130372c3130352c37312c34332c36392c34382c36362c36382c38312c36392c36372c36352c3131392c37332c36362c36352c3132322c36352c38312c36362c3130332c3131352c3131332c3130342c3130372c3130352c37312c34332c36392c34382c36362c36382c38312c36392c36372c36362c36352c37332c36362c36352c3132322c36352c38322c36362c3130332c3131352c3131332c3130342c3130372c3130352c37312c34332c36392c34382c36362c31302c36382c38312c36392c36372c36362c38312c37332c36372c36352c38302c35362c3131392c36392c38312c38392c37362c37352c3131312c39302c37332c3130342c3131382c3130342c37382c36352c38312c34382c36362c36352c3130332c38392c36372c36352c3130332c36382c34372c37372c36362c36352c37312c36372c3132312c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c37332c37322c36352c3130332c36392c36362c37372c36362c36352c37312c31302c36372c3132312c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c37332c37332c36352c3130332c36392c36352c37372c36362c36352c37312c36372c3132312c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c37332c37342c36352c3130332c36392c36352c37372c36362c36352c37312c36372c3132312c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c37332c37352c31302c36352c3130332c36392c36352c37372c36362c36352c37312c36372c3132312c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c37332c37362c36352c3130332c36392c36352c37372c36362c36352c37312c36372c3132312c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c37332c37372c36352c3130332c36392c36352c37372c36362c36352c37312c36372c3132312c3131332c37312c38332c37332c39382c35322c31302c38342c38312c36392c37382c36352c38312c37332c37382c36352c3130332c36392c36352c37372c36362c36352c37312c36372c3132312c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c37332c37392c36352c3130332c36392c36352c37372c36362c36352c37312c36372c3132312c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c37332c38302c36352c3130332c36392c36352c37372c36362c36352c37312c31302c36372c3132312c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c37332c38312c36352c3130332c36392c36352c37372c36362c36352c37312c36372c3132312c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c37332c38322c36352c3130332c36392c37382c37372c36362c35362c37312c36372c3132312c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c37332c38332c31302c36362c36362c36352c37372c36382c36352c37372c36382c34372c34372c35362c36362c36352c36352c36352c36352c36352c36352c36352c36352c36352c36352c36352c36352c37372c36362c36352c37312c36372c3130352c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c37372c36392c36352c3130332c36352c36352c37372c36362c38312c37312c36372c3130352c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c31302c36352c38312c38312c36392c36362c3130332c36362c3130332c39372c3130332c36352c36352c36352c36382c36352c38302c36362c3130332c3131312c3131332c3130342c3130372c3130352c37312c34332c36392c34382c36362c36382c38312c36392c37302c36372c3130332c36392c36362c37372c36362c35322c37312c36372c3130352c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c38392c36392c36392c37332c38322c39382c3130302c3130362c3131372c3130342c31302c35332c3131302c3130322c39392c3130392c3130372c36382c38332c36352c34372c39302c3130312c3131382c3130372c39392c3131392c38322c36352c38392c37352c37352c3131312c39302c37332c3130342c3131382c3130342c37382c36352c38312c34382c36362c36362c3132322c36352c35302c37372c36362c36352c37312c36372c3132312c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c39392c36362c36352c38312c37322c34372c37372c36362c36352c37312c31302c36372c3132312c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c39392c36372c36352c38312c36392c36352c37372c36362c36352c37312c36372c3132312c3131332c37312c38332c37332c39382c35322c38342c38312c36392c37382c36352c38312c39392c36382c36352c38312c36392c36352c37372c36352c3131312c37312c36372c36372c3131332c37312c38332c37372c35322c35372c36362c36352c37372c36372c36352c34382c39392c36352c31302c37372c36392c38312c36372c37332c37322c38302c36352c37372c37342c38352c3131362c37332c35322c35332c37352c3131352c37392c3130362c37382c36392c38322c38312c38322c3130362c3131342c39392c35342c38352c35342c3131312c3131322c35322c38362c3131312c3130302c35362c3131332c39382c38352c35302c3131342c37382c38382c3131322c38352c39302c38372c36352c3130352c36352c3131382c37362c3132322c3130342c3131322c39382c37342c3130342c34392c3130382c38312c3131302c3131322c31302c3130382c3131382c39382c3130372c38372c37392c34372c38372c3131382c3132312c35342c39382c37372c39392c35312c3130362c38322c3131352c39372c3131332c34382c3130342c38362c3131312c34382c38302c37392c36392c3130392c3130332c36312c36312c31302c34352c34352c34352c34352c34352c36392c37382c36382c33322c36372c36392c38322c38342c37332c37302c37332c36372c36352c38342c36392c34352c34352c34352c34352c34352c31302c34352c34352c34352c34352c34352c36362c36392c37312c37332c37382c33322c36372c36392c38322c38342c37332c37302c37332c36372c36352c38342c36392c34352c34352c34352c34352c34352c31302c37372c37332c37332c36372c3130382c3130362c36372c36372c36352c3130362c35302c3130332c36352c3131392c37332c36362c36352c3130332c37332c38362c36352c37342c38362c3131382c38382c39392c35302c35372c37312c34332c37322c3131322c38312c36392c3131302c37342c34392c38302c38312c3132322c3132322c3130332c37302c38382c36372c35372c35332c38352c37372c36352c3131312c37312c36372c36372c3131332c37312c38332c37372c35322c35372c36362c36352c37372c36372c31302c37372c37312c3130332c3132302c37312c3130362c36352c38392c36362c3130332c37382c38362c36362c36352c37372c37372c36392c38352c3130382c3131372c3130302c37312c38362c3131352c37332c37302c37382c37322c38372c36372c36362c38332c39382c35302c35372c34382c37332c36392c37382c36362c37372c38322c3131312c3131392c37312c36352c38392c36382c38362c38312c38312c37352c36382c36362c37302c37342c39382c3131302c38322c3130382c39382c36372c36362c36382c31302c39382c35312c37342c3131392c39382c35312c37342c3130342c3130302c37312c3130382c3131382c39382c3130362c36392c38352c37372c36362c37332c37312c36352c34392c38352c36392c36362c3131392c3131392c37362c38352c35302c37302c3131372c3130302c37312c36392c3130332c38312c35302c3132302c3130342c39392c3130392c36392c3132302c36372c3132322c36352c37342c36362c3130332c37382c38362c36362c36352c3130332c37372c36352c3130372c37382c36362c37372c38312c3131352c3131392c31302c36372c38312c38392c36382c38362c38312c38312c37312c36392c3131392c37342c38362c38352c3132322c36352c3130312c37302c3131392c34382c3132302c37392c36382c36352c34392c37372c3130362c36392c3132302c37372c36382c38352c3131392c37372c38342c36362c39372c37302c3131392c34382c3132322c37372c3132322c36352c34392c37372c3130362c36392c3132302c37372c36382c38352c3131392c37372c38342c36362c39372c37372c37322c36352c3132302c37332c3130362c36352c3130332c31302c36362c3130332c37382c38362c36362c36352c37372c37372c37312c38352c3130382c3131372c3130302c37312c38362c3131352c37332c37302c37382c37322c38372c36372c36362c38312c38312c34382c3131352c3130332c38352c37312c3132302c3130342c3130302c37312c39302c3131382c39392c3130392c34382c3130332c38312c34382c36392c3132302c37312c3130362c36352c38392c36362c3130332c37382c38362c36362c36352c3131312c37372c36392c38352c3130382c3131372c3130302c37312c38362c3131352c31302c37332c36392c37382c3131382c39392c3131302c36362c3131382c39392c3130392c37302c34382c39372c38372c35372c3131372c37372c38322c38312c3131392c36392c3130332c38392c36382c38362c38312c38312c37322c36382c36352c3131362c38342c38392c38372c35332c34382c38392c38332c36362c36382c39382c37312c37302c3132312c38392c38342c36392c37362c37372c36352c3130372c37312c36352c34392c38352c36392c36372c36352c3131392c36372c38312c34382c36392c3132302c31302c36372c3132322c36352c37342c36362c3130332c37382c38362c36362c36352c38392c38342c36352c3130382c38362c38342c37372c37302c3130372c3131392c36392c3131392c38392c37322c37352c3131312c39302c37332c3132322c3130362c34382c36372c36352c38312c38392c37332c37352c3131312c39302c37332c3132322c3130362c34382c36382c36352c38312c39392c36382c38312c3130332c36352c36392c37382c38332c36362c34372c35352c3131362c35302c34392c3130382c38382c38332c37392c31302c35302c36372c3131372c3132322c3131322c3132302c3131392c35352c35322c3130312c37342c36362c35352c35302c36392c3132312c36382c37312c3130332c38372c35332c3131342c38382c36372c3131362c3132302c35302c3131362c38362c38342c37362c3131332c35342c3130342c37352c3130372c35342c3132322c34332c38352c3130352c38322c39302c36372c3131302c3131332c38322c35352c3131322c3131352c37392c3131382c3130332c3131332c37302c3130312c38332c3132302c3130382c3130392c38342c3130382c37342c3130382c31302c3130312c38342c3130392c3130352c35302c38372c38392c3132322c35312c3131332c37392c36362c3131372c3132322c36372c36362c3131372c36382c36352c3130322c36362c3130332c37382c38362c37322c38332c37372c36392c37312c36382c36352c38372c3130332c36362c38312c3130352c39302c38312c3132322c38372c38372c3131322c34382c34382c3130352c3130322c37392c36382c3131362c37342c38362c38332c3131382c34392c36352c39382c37392c38332c39392c37312c3131342c36382c36362c38332c31302c36362c3130332c37382c38362c37322c38322c35362c36392c38332c3132322c36362c37342c37372c36392c3130312c3130332c38322c39372c36362c36382c3130342c3130372c37302c3131312c3130302c37322c38322c3131392c39392c3132322c3131312c3131382c37362c35302c37382c3130382c39392c3131302c38322c3131322c39302c3130392c3130382c3130362c38392c38382c38322c3130382c39392c3132312c35332c34382c39392c3131302c38362c3132322c3130302c37312c38362c3130372c39392c35302c38362c3132312c31302c3130302c3130392c3130382c3130362c39302c38382c37372c3131372c39372c38372c35332c34382c39302c38372c3131392c3131372c38392c35302c35372c3131362c37362c34382c3130382c3131372c3130302c37312c38362c3131352c38352c34382c3130302c38392c38352c3130392c35372c3131382c3130302c36392c37382c36362c37362c3130392c38322c3130382c39392c3130362c36352c3130302c36362c3130332c37382c38362c37322c38312c35322c36392c37302c3130332c38312c38352c3130382c38372c35372c3130302c31302c3132322c39382c34382c39382c35322c3130312c3130382c36352c38332c39392c3131302c38352c35372c36382c38302c37392c36352c38362c39392c37362c35312c3130382c38312c3131392c36382c3130332c38392c36382c38362c38322c34382c38302c36352c38312c37322c34372c36362c36352c38312c36382c36352c3130332c36392c37312c37372c36362c37332c37312c36352c34392c38352c3130302c36392c3131392c36392c36362c34372c3131392c38312c37332c37372c36352c38392c36362c31302c36352c3130322c35362c36372c36352c38312c36352c3131392c36372c3130332c38392c37332c37352c3131312c39302c37332c3132322c3130362c34382c36392c36352c3131392c37332c36382c38322c3131392c36352c3131392c38322c36352c37332c3130332c38382c3131352c38362c3130372c3130352c34382c3131392c34332c3130352c35342c38362c38392c37312c38372c35312c38352c37302c34372c35302c35302c3131372c39372c38382c3130312c34382c38392c37342c36382c3130362c34392c38352c3130312c31302c3131302c36352c34332c38342c3130362c36382c34392c39372c3130352c35332c39392c36372c37332c36372c38392c39382c34392c38332c36352c3130392c36382c35332c3132302c3130372c3130322c38342c38362c3131322c3131382c3131312c35322c38352c3131312c3132312c3130352c38332c38392c3132302c3131342c36382c38372c37362c3130392c38352c38322c35322c36372c37332c35372c37382c37352c3132312c3130322c38302c37382c34332c31302c34352c34352c34352c34352c34352c36392c37382c36382c33322c36372c36392c38322c38342c37332c37302c37332c36372c36352c38342c36392c34352c34352c34352c34352c34352c31302c34352c34352c34352c34352c34352c36362c36392c37312c37332c37382c33322c36372c36392c38322c38342c37332c37302c37332c36372c36352c38342c36392c34352c34352c34352c34352c34352c31302c37372c37332c37332c36372c3130362c3132322c36372c36372c36352c3130362c38332c3130332c36352c3131392c37332c36362c36352c3130332c37332c38352c37332c3130392c38352c37372c34392c3130382c3131332c3130302c37382c37332c3131302c3132322c3130332c35352c38332c38362c38352c3131342c35372c38312c37312c3132322c3130372c3131302c36362c3131332c3131392c3131392c36372c3130332c38392c37332c37352c3131312c39302c37332c3132322c3130362c34382c36392c36352c3131392c37332c3131392c31302c39372c36382c36392c39372c37372c36362c3130332c37312c36352c34392c38352c36392c36352c3131392c3131392c38322c38332c38372c35332c34382c39302c38372c3131392c3130332c38352c34382c3130302c38392c37332c37302c37342c3131382c39382c35312c38312c3130332c38312c34382c36392c3132302c37312c3130362c36352c38392c36362c3130332c37382c38362c36362c36352c3131312c37372c36392c38352c3130382c3131372c3130302c37312c38362c3131352c37332c36392c37382c3131382c31302c39392c3131302c36362c3131382c39392c3130392c37302c34382c39372c38372c35372c3131372c37372c38322c38312c3131392c36392c3130332c38392c36382c38362c38312c38312c37322c36382c36352c3131362c38342c38392c38372c35332c34382c38392c38332c36362c36382c39382c37312c37302c3132312c38392c38342c36392c37362c37372c36352c3130372c37312c36352c34392c38352c36392c36372c36352c3131392c36372c38312c34382c36392c3132302c36372c3132322c36352c37342c31302c36362c3130332c37382c38362c36362c36352c38392c38342c36352c3130382c38362c38342c37372c36362c35322c38382c36382c38342c36392c35322c37372c36382c38352c3132312c37372c38342c36392c3131392c37382c36382c38352c3132302c37372c37302c3131312c38382c36382c38342c38312c35332c37372c38342c37332c3132322c37372c38342c37332c3132322c37382c38342c3130372c34392c37392c38362c3131312c3131392c39372c36382c36392c39372c37372c36362c3130332c37312c31302c36352c34392c38352c36392c36352c3131392c3131392c38322c38332c38372c35332c34382c39302c38372c3131392c3130332c38352c34382c3130302c38392c37332c37302c37342c3131382c39382c35312c38312c3130332c38312c34382c36392c3132302c37312c3130362c36352c38392c36362c3130332c37382c38362c36362c36352c3131312c37372c36392c38352c3130382c3131372c3130302c37312c38362c3131352c37332c36392c37382c3131382c39392c3131302c36362c3131382c39392c3130392c37302c34382c31302c39372c38372c35372c3131372c37372c38322c38312c3131392c36392c3130332c38392c36382c38362c38312c38312c37322c36382c36352c3131362c38342c38392c38372c35332c34382c38392c38332c36362c36382c39382c37312c37302c3132312c38392c38342c36392c37362c37372c36352c3130372c37312c36352c34392c38352c36392c36372c36352c3131392c36372c38312c34382c36392c3132302c36372c3132322c36352c37342c36362c3130332c37382c38362c36362c36352c38392c38342c31302c36352c3130382c38362c38342c37372c37302c3130372c3131392c36392c3131392c38392c37322c37352c3131312c39302c37332c3132322c3130362c34382c36372c36352c38312c38392c37332c37352c3131312c39302c37332c3132322c3130362c34382c36382c36352c38312c39392c36382c38312c3130332c36352c36392c36372c35342c3131302c36392c3131392c37372c36382c37332c38392c39302c37392c3130362c34372c3130352c38302c38372c3131352c36372c3132322c39372c36392c37352c3130352c35352c31302c34392c37392c3130352c37392c38332c37362c38322c37302c3130342c38372c37312c3130362c39382c3131302c36362c38362c37342c3130322c38362c3131302c3130372c38392c35322c3131372c35312c37332c3130362c3130372c36382c38392c38392c37362c34382c37372c3132302c37392c35322c3130392c3131332c3131352c3132312c38392c3130362c3130382c36362c39372c3130382c38342c38362c38392c3132302c37302c38302c35302c3131352c37342c36362c37352c35332c3132322c3130382c37352c37392c36362c31302c3131372c3132322c36372c36362c3131372c36382c36352c3130322c36362c3130332c37382c38362c37322c38332c37372c36392c37312c36382c36352c38372c3130332c36362c38312c3130352c39302c38312c3132322c38372c38372c3131322c34382c34382c3130352c3130322c37392c36382c3131362c37342c38362c38332c3131382c34392c36352c39382c37392c38332c39392c37312c3131342c36382c36362c38332c36362c3130332c37382c38362c37322c38322c35362c36392c38332c3132322c36362c37342c31302c37372c36392c3130312c3130332c38322c39372c36362c36382c3130342c3130372c37302c3131312c3130302c37322c38322c3131392c39392c3132322c3131312c3131382c37362c35302c37382c3130382c39392c3131302c38322c3131322c39302c3130392c3130382c3130362c38392c38382c38322c3130382c39392c3132312c35332c34382c39392c3131302c38362c3132322c3130302c37312c38362c3130372c39392c35302c38362c3132312c3130302c3130392c3130382c3130362c39302c38382c37372c3131372c39372c38372c35332c34382c31302c39302c38372c3131392c3131372c38392c35302c35372c3131362c37362c34382c3130382c3131372c3130302c37312c38362c3131352c38352c34382c3130302c38392c38352c3130392c35372c3131382c3130302c36392c37382c36362c37362c3130392c38322c3130382c39392c3130362c36352c3130302c36362c3130332c37382c38362c37322c38312c35322c36392c37302c3130332c38312c38352c37332c3130392c38352c37372c34392c3130382c3131332c3130302c37382c37332c3131302c3132322c3130332c35352c38332c38362c31302c38352c3131342c35372c38312c37312c3132322c3130372c3131302c36362c3131332c3131392c3131392c36382c3130332c38392c36382c38362c38322c34382c38302c36352c38312c37322c34372c36362c36352c38312c36382c36352c3130332c36392c37312c37372c36362c37332c37312c36352c34392c38352c3130302c36392c3131392c36392c36362c34372c3131392c38312c37332c37372c36352c38392c36362c36352c3130322c35362c36372c36352c38312c36392c3131392c36372c3130332c38392c37332c31302c37352c3131312c39302c37332c3132322c3130362c34382c36392c36352c3131392c37332c36382c38332c38312c36352c3131392c38322c3130332c37332c3130342c36352c37392c38372c34372c35332c38312c3130372c38322c34332c38332c35372c36372c3130352c38332c36382c39392c37382c3131312c3131312c3131392c37362c3131372c38302c38322c37362c3131352c38372c37312c3130322c34372c38392c3130352c35352c37312c38332c38382c35372c35322c36362c3130332c3131392c38342c3131392c3130332c31302c36352c3130352c36392c36352c35322c37342c34382c3130382c3131342c37322c3131312c37372c3131352c34332c38382c3131312c35332c3131312c34372c3131352c38382c35342c37392c35372c38312c38372c3132302c37322c38322c36352c3131382c39302c38352c37312c37392c3130302c38322c38312c35352c39392c3131382c3131332c38322c38382c39372c3131332c37332c36312c31302c34352c34352c34352c34352c34352c36392c37382c36382c33322c36372c36392c38322c38342c37332c37302c37332c36372c36352c38342c36392c34352c34352c34352c34352c34352c31302c305d2c22666e5f6b6579223a5b3234322c3135342c3235312c3234332c3131382c3232312c39302c3235342c3133352c3230362c3231312c33372c392c3137322c3135392c3233302c3137322c3235352c38332c3232302c32322c39302c39352c3235332c3231332c3234322c34302c33382c33332c39372c3231302c3134355d2c227369676e6572223a5b35302c3130302c342c33332c37372c3134302c3133312c312c3234392c3137392c37312c3139342c3136342c34342c35302c3131392c3133322c32372c3231382c3139362c3132322c36322c3132392c3138372c39332c39302c3230372c37352c36322c3133392c3137362c3231335d2c22666e5f726571756573745f6b6579223a5b5d2c22666e5f726571756573745f68617368223a5b5d2c22636861696e5f726573756c745f696e666f223a7b22536f6c616e61223a7b2273657269616c697a65645f7478223a5b332c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c302c3134342c38372c3133312c3138392c3130392c38352c3133372c3234322c3136372c3234332c3234312c3134322c382c3130372c34392c3232332c3138382c31302c3135362c3131312c3139362c3136332c39312c36392c3131332c31342c3137392c3231312c3137342c3133322c332c3234372c3136352c35302c3139332c3231332c3230332c3234372c31372c3232352c3233352c3234362c33392c3132312c3234332c34362c3233362c37372c36332c382c3232322c3136342c3133372c3234302c3232332c34392c38322c302c3230392c3233302c38332c36352c3138312c362c332c322c372c31342c31392c3136352c33392c3131392c3135392c31392c37382c3136322c32302c36332c3133312c35332c37352c3132322c39352c35302c3230312c36392c3230392c3133342c3138302c37322c3235322c32322c35302c3132302c39372c3136312c3139322c3234372c3132322c3234382c33362c3137372c3130342c39392c37332c3139362c3134382c3138372c3231312c35302c3136352c3139392c3137302c35312c3135352c3135372c39322c3136312c3232332c39382c36332c3137312c3235342c31362c34332c38312c39322c3138362c38392c31382c3130322c3230332c35302c3130302c342c33332c37372c3134302c3133312c312c3234392c3137392c37312c3139342c3136342c34342c35302c3131392c3133322c32372c3231382c3139362c3132322c36322c3132392c3138372c39332c39302c3230372c37352c36322c3133392c3137362c3231332c36382c36362c3232312c3139372c3133382c3232382c3134332c35392c3139392c3132392c3231342c39342c3234312c302c31372c3133322c3235332c3231312c3231302c3138382c3132342c3139372c31352c3130392c34382c36332c3136382c3235352c38332c34322c3234382c32302c3131342c3133392c3136382c3133372c3130302c3232392c3232332c3135352c31372c38392c3139302c3131312c35302c3233332c33312c3134312c3233372c3134372c3132302c33322c3232372c3136302c3136372c342c3230302c3233302c37342c3230332c3138332c3235312c35302c35322c3136392c3138342c3138322c3137342c38372c38302c36312c332c3232342c3135322c3233382c34352c32382c31332c3131392c3134392c302c33372c32362c38322c3130302c3139372c37372c32372c3139322c3231362c35322c3132322c3136322c31332c39392c37352c3234322c3135342c3235312c3234332c3131382c3232312c39302c3235342c3133352c3230362c3231312c33372c392c3137322c3135392c3233302c3137322c3235352c38332c3232302c32322c39302c39352c3235332c3231332c3234322c34302c33382c33332c39372c3231302c3134352c362c3232312c3234362c3232352c3231352c3130312c3136312c3134372c3231372c3230332c3232352c37302c3230362c3233352c3132312c3137322c32382c3138302c3133332c3233372c39352c39312c35352c3134352c35382c3134302c3234352c3133332c3132362c3235352c302c3136392c31322c3234362c33372c34302c3135362c3134362c3136312c3133322c3139302c3132302c3230312c31382c3136312c38312c3138392c3231352c38312c32382c3234332c3138392c38312c3233302c3139382c33372c3132372c3138392c3233372c34352c3138302c332c3138382c3139312c36342c3234362c3138342c34342c3230352c36332c3132342c3233312c33392c3135312c3234322c3137342c3139322c33362c3131352c3132332c39312c3139352c39302c3135342c39312c33342c33322c3134372c39312c3131322c3130392c3230362c32382c3133392c3136312c35302c38302c3138372c3234382c31352c38352c32302c3234372c36332c3132322c38392c38342c3138352c3234372c3131332c3234362c36302c35362c3230372c35332c33302c3132302c31332c3130392c36322c31322c38322c36392c3130322c37322c3230332c39302c37352c38312c33312c3232352c37392c3233372c3130342c3138332c33322c3139322c32302c3137372c3132342c3136322c36382c3133382c3139322c3231322c3230342c32372c35312c31382c3137362c36302c3230362c3234362c3135362c3131362c3134372c33382c36392c3136342c3134392c3139362c3139352c3231392c3232312c3134312c32392c35372c3134322c352c3137392c3137352c37352c3138342c3139342c3134332c3235342c3231312c3231332c3235302c3130302c3231342c3135352c3233392c35392c3139382c3138312c36382c32302c3134392c382c3233312c34352c3232332c3230332c35332c31372c3133372c33372c392c3232322c33312c3230342c3136302c3138342c3235352c3133352c3139342c3138352c38322c3136302c3134312c3235302c3235302c3136332c3132332c34382c39352c3235342c3136392c31302c39352c3233312c39332c32322c38302c35382c322c35302c3139312c39322c3234392c3133382c3233362c38312c392c3233362c3135362c3234352c3233322c39332c3135352c3233362c3139352c3234382c36352c36372c3230322c3231342c3235312c37342c3233342c3133372c36312c35332c32332c36332c322c382c31302c362c322c31332c312c392c31302c332c352c31312c372c35372c3231302c3130382c3135342c3133382c3139382c31342c35332c3139312c3135312c3135312c36372c3130312c302c302c302c302c3235352c3235352c3235352c3235352c3235352c3235352c3235352c3132372c302c32332c3235352c3135322c3234302c372c3134302c3232392c3130352c3133312c3138372c36322c3136302c31372c3230302c3137372c3135362c3233382c3231332c3234322c3135362c3135332c39342c352c37372c39312c3231382c3138332c3134362c3138312c3230362c3137332c3130382c31322c332c342c362c322c3135312c322c32302c3231362c3234362c35312c37322c3232362c3230372c3136302c332c302c302c302c312c3135312c3135312c36372c3130312c302c302c302c302c3132382c35382c3231302c35312c34362c33322c302c302c302c302c302c302c302c302c302c302c3132382c3135352c3135322c32322c3233332c302c302c302c302c302c302c302c302c302c302c302c33322c3230352c34382c3136392c33322c35392c302c302c302c302c302c302c302c302c302c302c37342c38312c3232312c3234302c34322c33322c302c302c302c302c302c302c302c302c302c302c3234362c3133382c3130362c3231392c3231352c33312c302c302c302c302c302c302c302c302c302c302c322c3135312c3135312c36372c3130312c302c302c302c302c302c392c37392c3138352c3137312c312c302c302c302c302c302c302c302c302c302c302c39362c33362c3231392c3132322c3130382c392c302c302c302c302c302c302c302c302c302c302c33322c3130392c38332c35332c37342c3234332c312c302c302c302c302c302c302c302c302c302c3138382c36352c34312c3135392c3137312c312c302c302c302c302c302c302c302c302c302c302c34382c39382c3134312c3134322c3137302c312c302c302c302c302c302c302c302c302c302c302c332c3135312c3135312c36372c3130312c302c302c302c302c3232342c34302c3134372c35392c302c302c302c302c302c302c302c302c302c302c302c302c302c3234302c3230362c3130342c3135362c3131302c3137342c302c302c302c302c302c302c302c302c302c302c32382c3232322c3135312c3138362c3230302c38362c372c302c302c302c302c302c302c302c302c38322c38342c3134352c35392c302c302c302c302c302c302c302c302c302c302c302c302c3232302c3233382c3134382c35392c302c302c302c302c302c302c302c302c302c302c302c305d7d7d2c226572726f725f636f6465223a307d";
617
618 #[test]
619 fn test_legacy_decode() {
620 let _ = simple_logger::init_with_level(log::Level::Debug);
621
622 let decoded =
623 FunctionResult::decode(&format!("FN_OUT: {}", EMPTY_ENCODED_FN_RESULT)).unwrap();
624
625 assert_eq!(decoded, FunctionResult::V0(FunctionResultV0::default()));
626 }
627
628 #[test]
629 fn test_legacy_quote() {
630 let _ = simple_logger::init_with_level(log::Level::Debug);
631
632 let mut rng = rand::thread_rng();
633
634 let quote: Vec<u8> = (0..1456).map(|_| rng.gen::<u8>()).collect();
635 let fn_key: Vec<u8> = (0..32).map(|_| rng.gen::<u8>()).collect();
636 let signer: Vec<u8> = (0..32).map(|_| rng.gen::<u8>()).collect();
637
638 let legacy = LegacyFunctionResult {
639 fn_key: fn_key.clone(),
640 version: 1,
641 quote: quote.clone(),
642 signer: signer.clone(),
643 fn_request_key: vec![],
644 fn_request_hash: vec![],
645 chain_result_info: LegacyChainResultInfo::default(),
646 error_code: 1,
647 };
648
649 let function_result: FunctionResult = legacy.into();
650
651 assert_eq!(quote, function_result.quote_bytes().to_vec());
654 assert_eq!(fn_key, function_result.fn_key().unwrap());
655 assert_eq!(signer, function_result.signer().to_vec());
656 }
657
658 #[test]
659 fn test_decode() {
660 let _ = simple_logger::init_with_level(log::Level::Debug);
661
662 let fr = FunctionResult::default();
663
664 let encoded = format!(
665 "FN_OUT: {}",
666 hex::encode(serde_json::to_string(&fr).unwrap())
667 );
668 let decoded = FunctionResult::decode(&encoded).unwrap();
671 assert_eq!(decoded, FunctionResult::default());
674 }
675
676 #[test]
677 fn test_case_1() {
678 let _ = simple_logger::init_with_level(log::Level::Debug);
679 let _decoded = FunctionResult::decode(TEST_CASE_1).unwrap();
680 }
682
683 #[test]
684 fn test_evm_v0_decode() {
685 let _ = simple_logger::init_with_level(log::Level::Debug);
686
687 let evm_result = EvmFunctionResultV0::default();
688 let fr = FunctionResult::V0(FunctionResultV0 {
689 quote: vec![],
690 fn_key: vec![],
691 signer: vec![],
692 fn_request_key: vec![],
693 fn_request_hash: vec![],
694 chain_result_info: ChainResultInfo::Evm(EvmFunctionResult::V0(evm_result)),
695 error_code: 0,
696 });
697
698 let encoded = format!(
699 "FN_OUT: {}",
700 hex::encode(serde_json::to_string(&fr).unwrap())
701 );
702 let decoded = FunctionResult::decode(&encoded).unwrap();
705 match decoded {
708 FunctionResult::V0(FunctionResultV0 {
709 chain_result_info:
710 ChainResultInfo::Evm(EvmFunctionResult::V0(decoded_evm_v0_result)),
711 ..
712 }) => {
713 assert_eq!(decoded_evm_v0_result, EvmFunctionResultV0::default());
714 }
715 _ => panic!("Expected EVMFunctionResultV0"),
716 }
717 }
718}