Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
149 changes: 99 additions & 50 deletions libs/ur-registry/src/avalanche/avax_sign_request.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
use crate::cbor::{cbor_array, cbor_map};
use crate::error::{URError, URResult};
use crate::registry_types::{RegistryType, AVAX_SIGN_REQUEST, UUID};
use crate::registry_types::{RegistryType, AVAX_SIGN_REQUEST, UUID, CRYPTO_KEYPATH, AVAX_UTXO};
use crate::crypto_key_path::CryptoKeyPath;
use crate::traits::{From as FromCbor, RegistryItem, To};
use crate::types::{Bytes, Fingerprint};
use super::avax_utxo::AvaxUtxo;
use alloc::string::{String, ToString};
use alloc::vec::Vec;
use minicbor::data::{Int, Tag};
Expand All @@ -11,33 +13,29 @@ use minicbor::{Decoder, Encoder};

const REQUEST_ID: u8 = 1;
const SIGN_DATA: u8 = 2;
const MASTER_FINGERPRINT: u8 = 3;
const XPUB: u8 = 6;
const WALLET_INDEX: u8 = 7;
const DERIVATION_PATH: u8 = 3;
const UTXOS: u8 = 4;

#[derive(Debug, Clone, Default)]
pub struct AvaxSignRequest {
request_id: Bytes,
sign_data: Bytes,
master_fingerprint: Fingerprint,
xpub: String,
wallet_index: u64,
derivation_path: Vec<CryptoKeyPath>,
utxos: Vec<AvaxUtxo>,
}

impl AvaxSignRequest {
pub fn new(
request_id: Bytes,
sign_data: Bytes,
master_fingerprint: Fingerprint,
xpub: String,
wallet_index: u64,
derivation_path: Vec<CryptoKeyPath>,
utxos: Vec<AvaxUtxo>,
) -> Self {
AvaxSignRequest {
request_id,
sign_data,
master_fingerprint,
xpub,
wallet_index,
derivation_path,
utxos: utxos,
}
}

Expand All @@ -57,24 +55,20 @@ impl AvaxSignRequest {
self.sign_data = data;
}

pub fn get_master_fingerprint(&self) -> Fingerprint {
self.master_fingerprint
pub fn get_derivation_path(&self) -> Vec<CryptoKeyPath> {
self.derivation_path.clone()
}

pub fn get_xpub(&self) -> String {
self.xpub.clone()
pub fn set_derivation_path(&mut self, derivation_path: Vec<CryptoKeyPath>) {
self.derivation_path = derivation_path;
}

pub fn set_xpub(&mut self, xpub: String) {
self.xpub = xpub;
pub fn get_utxos(&self) -> Vec<AvaxUtxo> {
self.utxos.clone()
}

pub fn get_wallet_index(&self) -> u64 {
self.wallet_index
}

pub fn set_wallet_index(&mut self, index: u64) {
self.wallet_index = index;
pub fn set_utxos(&mut self, utxos: Vec<AvaxUtxo>) {
self.utxos = utxos;
}
}

Expand All @@ -90,23 +84,43 @@ impl<C> minicbor::Encode<C> for AvaxSignRequest {
e: &mut Encoder<W>,
_ctx: &mut C,
) -> Result<(), minicbor::encode::Error<W::Error>> {
e.map(5)?;
let utxos = self.get_utxos();
let map_size = if utxos.is_empty() { 3 } else { 4 };

e.map(map_size)?;
e.int(Int::from(REQUEST_ID))?
.tag(Tag::Unassigned(UUID.get_tag()))?
.bytes(&self.request_id)?;
e.int(Int::from(SIGN_DATA))?.bytes(&self.sign_data)?;
e.int(Int::from(MASTER_FINGERPRINT))?.int(
Int::try_from(u32::from_be_bytes(self.master_fingerprint))
.map_err(|e| minicbor::encode::Error::message(e.to_string()))?,
)?;
e.int(Int::from(XPUB))?.str(&self.xpub)?;
e.int(Int::from(WALLET_INDEX))?.u64(self.wallet_index)?;

let key_derivation_paths = self.get_derivation_path();
if key_derivation_paths.is_empty() {
return Err(minicbor::encode::Error::message(
"key derivation paths is invalid",
));
}

e.int(Int::from(DERIVATION_PATH))?.array(key_derivation_paths.len() as u64)?;
for path in key_derivation_paths {
e.tag(Tag::Unassigned(CRYPTO_KEYPATH.get_tag()))?;
CryptoKeyPath::encode(&path, e, _ctx)?;
}

if !utxos.is_empty() {
e.int(Int::from(UTXOS))?
.array(utxos.len() as u64)?;
for utxo in utxos {
e.tag(Tag::Unassigned(AvaxUtxo::get_registry_type().get_tag()))?;
AvaxUtxo::encode(&utxo, e, _ctx)?;
}
}

Ok(())
}
}

impl<'b, C> minicbor::Decode<'b, C> for AvaxSignRequest {
fn decode(d: &mut Decoder<'b>, _ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
fn decode(d: &mut Decoder<'b>, ctx: &mut C) -> Result<Self, minicbor::decode::Error> {
let mut result = AvaxSignRequest::default();

cbor_map(d, &mut result, |key, obj, d| {
Expand All @@ -120,16 +134,37 @@ impl<'b, C> minicbor::Decode<'b, C> for AvaxSignRequest {
SIGN_DATA => {
obj.sign_data = d.bytes()?.to_vec();
}
MASTER_FINGERPRINT => {
let mfp = u32::try_from(d.int()?)
.map_err(|e| minicbor::decode::Error::message(e.to_string()));
obj.master_fingerprint = u32::to_be_bytes(mfp?);
}
XPUB => {
obj.xpub = d.str()?.to_string();
DERIVATION_PATH => {
cbor_array(
d,
&mut obj.derivation_path,
|_key, obj, d| {
let tag = d.tag()?;
if !tag.eq(&Tag::Unassigned(
CryptoKeyPath::get_registry_type().get_tag(),
)) {
return Err(minicbor::decode::Error::message(
"CryptoKeyPath tag is invalid",
));
}
obj.push(CryptoKeyPath::decode(d, ctx)?);
Ok(())
},
)?;
}
WALLET_INDEX => {
obj.wallet_index = d.u64()?;
UTXOS => {
cbor_array(d, &mut obj.utxos, |_key, obj, d| {
let tag = d.tag()?;
if !tag.eq(&Tag::Unassigned(
AvaxUtxo::get_registry_type().get_tag(),
)) {
return Err(minicbor::decode::Error::message(
"AvaxUtxo tag is invalid",
));
}
obj.push(AvaxUtxo::decode(d, ctx)?);
Ok(())
})?;
}
_ => {}
}
Expand Down Expand Up @@ -157,35 +192,49 @@ mod tests {
use crate::traits::RegistryItem;
use alloc::vec::Vec;
use hex::FromHex;
use crate::crypto_key_path::{CryptoKeyPath, PathComponent};
use alloc::vec;
extern crate std;
use std::println;

#[test]
fn test_avax_encode() {
let components = vec![
PathComponent::new(Some(44), true).unwrap(),
PathComponent::new(Some(9000), true).unwrap(),
PathComponent::new(Some(0), true).unwrap(),
PathComponent::new(Some(0), false).unwrap(),
PathComponent::new(Some(0), false).unwrap(),
];
let utxos = vec![];
let unsigned_data = AvaxSignRequest {
request_id: [12, 34, 56, 78].to_vec(),
sign_data: Vec::from_hex("000000000022000000050000000000000000000000000000000000000000000000000000000000000000000000023d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa0000000700000000000f42400000000000000000000000010000000132336f8715dd313a426155cccc15ba27c3033dae3d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000007000000004d58ade90000000000000000000000010000000132336f8715dd313a426155cccc15ba27c3033dae00000001410b47f7c7aa13f88122be58735c5e985edc65d86fb0baf0b016359c22253d75000000013d9bdac0ed1d761330cf680efdeb1a42159eb387d6d2950c96f7d28f61bbe2aa00000005000000004d680464000000010000000000000000")
sign_data: Vec::from_hex("0000000000220000000100000000000000000000000000000000000000000000000000000000000000000000000221e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff000000070000000000007d4c00000000000000000000000100000001b5e66be5c7093d1114d74940333c0c45f81092c521e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff000000070000000002ed658f00000000000000000000000100000001b5e66be5c7093d1114d74940333c0c45f81092c500000001918cf421e834d4d7031175ac9605ba292ee04a17beb4fb81f8557969b4651b860000000121e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff000000050000000002edf716000000010000000000000000")
.unwrap(),
master_fingerprint: [0, 0, 0, 0],
xpub: "xpub6DXryz8Kd7XchtXvDnkjara83shGJH8ubu7KZhHhPfp4L1shvDEYiFZm32EKHnyo4bva4gxXjabFGqY7fNs8Ggd4khYz2oNs2KYLf56a9GX".to_string(),
wallet_index: 0,
derivation_path: vec![CryptoKeyPath::new(
components,
Some([45,11,218,188]),
None,
)],
utxos
};
let result: Vec<u8> = unsigned_data.try_into().unwrap();
println!("result = {:?}", hex::encode(&result));
let ur = ur::encode(&result, AvaxSignRequest::get_registry_type().get_type());
assert_eq!(ur, "ur:avax-sign-request/onadtpdafybncpetglaohkaddmaeaeaeaeaecpaeaeaeahaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaofsndtnrtwecakobwdytkisbazcwmcyfwbznnqdlttbtdmdbnmtyltdmyhsrkvopkaeaeaeataeaeaeaeaebsfwfzaeaeaeaeaeaeaeaeaeaeaeadaeaeaeadeyeojlltbzutehftfwhsgosfsfbzrddisraxfsplfsndtnrtwecakobwdytkisbazcwmcyfwbznnqdlttbtdmdbnmtyltdmyhsrkvopkaeaeaeataeaeaeaegthdpmwlaeaeaeaeaeaeaeaeaeaeaeadaeaeaeadeyeojlltbzutehftfwhsgosfsfbzrddisraxfsplaeaeaeadfpbdflylstpkbwyalycprnhdjkhhhymkhyuoihtpjlpfrdwtpfcmecnscpdafskpaeaeaeadfsndtnrtwecakobwdytkisbazcwmcyfwbznnqdlttbtdmdbnmtyltdmyhsrkvopkaeaeaeahaeaeaeaegtisaaieaeaeaeadaeaeaeaeaeaeaeaeaxaeamksjlksjokpidenfyhdjpkkknetgrieemhdiaisjyhdkofyjtjeimhsjphseteojkisflgefdetkpidkpemgrhtisfdisgdiyjoeegsehjkiskofyfehkinfghtjneoeyfegrfdjtkkjleeidkohseeiokshdimhsidfgfljshkemiygljketflioieeejeishkkneyjlgljkeygrhkgsiyecenhsesflhdataedapawecf");
assert_eq!(ur, "ur:avax-sign-request/otadtpdafybncpetglaohkaddmaeaeaeaeaecpaeaeaeadaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaoclvajkchsbssrndrwmaeiokntbfgdikspdykcpjyrhtbahurdameprdydipdkizmaeaeaeataeaeaeaeaeaekigsaeaeaeaeaeaeaeaeaeaeaeadaeaeaeadrevajevwstasfsbybbtsgafzeofnbnfeyabemoskclvajkchsbssrndrwmaeiokntbfgdikspdykcpjyrhtbahurdameprdydipdkizmaeaeaeataeaeaeaeaoweihmyaeaeaeaeaeaeaeaeaeaeaeadaeaeaeadrevajevwstasfsbybbtsgafzeofnbnfeyabemoskaeaeaeadmelkwkclvseetytsaxbykppsmtahrddtdmvtgechrnqzzolyyagokkinqzihcwlnaeaeaeadclvajkchsbssrndrwmaeiokntbfgdikspdykcpjyrhtbahurdameprdydipdkizmaeaeaeahaeaeaeaeaoweylcmaeaeaeadaeaeaeaeaeaeaeaeaxlytaaddyoeadlecsdwykcfcndeykaeykaewkaewkaocydpbdtnrfcxutdyjn");
}

#[test]
fn test_avax_decode() {
let ur_string = "ur:avax-sign-request/otadtpdafybncpetglaohkaddmaeaeaeaeaecpaeaeaeahaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaeaofsndtnrtwecakobwdytkisbazcwmcyfwbznnqdlttbtdmdbnmtyltdmyhsrkvopkaeaeaeataeaeaeaeaebsfwfzaeaeaeaeaeaeaeaeaeaeaeadaeaeaeadeyeojlltbzutehftfwhsgosfsfbzrddisraxfsplfsndtnrtwecakobwdytkisbazcwmcyfwbznnqdlttbtdmdbnmtyltdmyhsrkvopkaeaeaeataeaeaeaegthdpmwlaeaeaeaeaeaeaeaeaeaeaeadaeaeaeadeyeojlltbzutehftfwhsgosfsfbzrddisraxfsplaeaeaeadfpbdflylstpkbwyalycprnhdjkhhhymkhyuoihtpjlpfrdwtpfcmecnscpdafskpaeaeaeadfsndtnrtwecakobwdytkisbazcwmcyfwbznnqdlttbtdmdbnmtyltdmyhsrkvopkaeaeaeahaeaeaeaegtisaaieaeaeaeadaeaeaeaeaeaeaeaeaxtaaddyoeadlecsdwykcfcndeykaeykaewkaewkaocybggdrprfknlulrbk";

let bytes =
Vec::from_hex("a501d825440c22384e0258de00000000000000000001ed5f38341e436e5d46e2bb00b45d62ae97d1b050c64bc634ae10626739e35c4b0000000121e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff00000007000000000089544000000000000000000000000100000001512e7191685398f00663e12197a3d8f6012d9ea300000001db720ad6707915cc4751fb7e5491a3af74e127a1d81817abe9438590c0833fe10000000021e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff000000050000000000989680000000010000000000000000031a0102030406786f7870756236445872797a384b6437586368745876446e6b6a61726138337368474a4838756275374b5a684868506670344c3173687644455969465a6d3332454b486e796f34627661346778586a61624647715937664e7338476764346b68597a326f4e73324b594c663536613947580706")
Vec::from_hex("a401d82550d797b45aef4b483cb106506e288b2c77025903960000000000220000000100000000000000000000000000000000000000000000000000000000000000000000000221e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff00000007000000000031cb3a00000000000000000000000100000001b5e66be5c7093d1114d74940333c0c45f81092c521e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff000000070000000005dabac900000000000000000000000100000001b5e66be5c7093d1114d74940333c0c45f81092c500000008120d0def706b8b759935b8ea9727662aafa5381e598a074daddc82492549cd760000000021e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff00000005000000000046239d0000000100000000174d1a9b28e1d4d518f1999d4f8ac422b8a3a4755001f5965e8d05c93359feb10000000021e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff00000005000000000131021c0000000100000000174d1a9b28e1d4d518f1999d4f8ac422b8a3a4755001f5965e8d05c93359feb10000000121e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff00000005000000000176b6a5000000010000000065a3b1de10620296debfa01aa953e45ddd19d2c39e3dacb9a92e6a85ca8a309c0000000021e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff00000005000000000098968000000001000000006f6522ae52b0231076dc63ff95f7ea22e2fd80943e37235302c7ee32afce4cd60000000021e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff0000000500000000009896800000000100000000845649c3d1a630d8b466f7b727f6577cb4a17864699e6de756e484b81d84cd2a0000000021e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff0000000500000000006c2b440000000100000000d1e6480c1825197e2ec293a60bacdc7f60bfba2f3cc5383855180b45d595a7030000000021e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff0000000500000000007a12000000000100000000f59b9a175ebe4ccd8de5dcfc6a26870414f30c696cce19283f30145624b445b70000000021e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff00000005000000000107a4930000000100000000000000000382d90130a2018a182cf5192328f500f500f400f4021a2d0bdabcd90130a2018a182cf5192328f500f500f401f4021a2d0bdabc0480")
.unwrap();
let data = AvaxSignRequest::try_from(bytes).unwrap();
assert_eq!(
data.get_tx_data(),
Vec::from_hex("00000000000000000001ed5f38341e436e5d46e2bb00b45d62ae97d1b050c64bc634ae10626739e35c4b0000000121e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff00000007000000000089544000000000000000000000000100000001512e7191685398f00663e12197a3d8f6012d9ea300000001db720ad6707915cc4751fb7e5491a3af74e127a1d81817abe9438590c0833fe10000000021e67317cbc4be2aeb00677ad6462778a8f52274b9d605df2591b23027a87dff000000050000000000989680000000010000000000000000")
.unwrap()
[0, 0, 0, 0, 0, 34, 0, 0, 0, 1, 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, 0, 0, 0, 0, 0, 0, 0, 2, 33, 230, 115, 23, 203, 196, 190, 42, 235, 0, 103, 122, 214, 70, 39, 120, 168, 245, 34, 116, 185, 214, 5, 223, 37, 145, 178, 48, 39, 168, 125, 255, 0, 0, 0, 7, 0, 0, 0, 0, 0, 49, 203, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 181, 230, 107, 229, 199, 9, 61, 17, 20, 215, 73, 64, 51, 60, 12, 69, 248, 16, 146, 197, 33, 230, 115, 23, 203, 196, 190, 42, 235, 0, 103, 122, 214, 70, 39, 120, 168, 245, 34, 116, 185, 214, 5, 223, 37, 145, 178, 48, 39, 168, 125, 255, 0, 0, 0, 7, 0, 0, 0, 0, 5, 218, 186, 201, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 181, 230, 107, 229, 199, 9, 61, 17, 20, 215, 73, 64, 51, 60, 12, 69, 248, 16, 146, 197, 0, 0, 0, 8, 18, 13, 13, 239, 112, 107, 139, 117, 153, 53, 184, 234, 151, 39, 102, 42, 175, 165, 56, 30, 89, 138, 7, 77, 173, 220, 130, 73, 37, 73, 205, 118, 0, 0, 0, 0, 33, 230, 115, 23, 203, 196, 190, 42, 235, 0, 103, 122, 214, 70, 39, 120, 168, 245, 34, 116, 185, 214, 5, 223, 37, 145, 178, 48, 39, 168, 125, 255, 0, 0, 0, 5, 0, 0, 0, 0, 0, 70, 35, 157, 0, 0, 0, 1, 0, 0, 0, 0, 23, 77, 26, 155, 40, 225, 212, 213, 24, 241, 153, 157, 79, 138, 196, 34, 184, 163, 164, 117, 80, 1, 245, 150, 94, 141, 5, 201, 51, 89, 254, 177, 0, 0, 0, 0, 33, 230, 115, 23, 203, 196, 190, 42, 235, 0, 103, 122, 214, 70, 39, 120, 168, 245, 34, 116, 185, 214, 5, 223, 37, 145, 178, 48, 39, 168, 125, 255, 0, 0, 0, 5, 0, 0, 0, 0, 1, 49, 2, 28, 0, 0, 0, 1, 0, 0, 0, 0, 23, 77, 26, 155, 40, 225, 212, 213, 24, 241, 153, 157, 79, 138, 196, 34, 184, 163, 164, 117, 80, 1, 245, 150, 94, 141, 5, 201, 51, 89, 254, 177, 0, 0, 0, 1, 33, 230, 115, 23, 203, 196, 190, 42, 235, 0, 103, 122, 214, 70, 39, 120, 168, 245, 34, 116, 185, 214, 5, 223, 37, 145, 178, 48, 39, 168, 125, 255, 0, 0, 0, 5, 0, 0, 0, 0, 1, 118, 182, 165, 0, 0, 0, 1, 0, 0, 0, 0, 101, 163, 177, 222, 16, 98, 2, 150, 222, 191, 160, 26, 169, 83, 228, 93, 221, 25, 210, 195, 158, 61, 172, 185, 169, 46, 106, 133, 202, 138, 48, 156, 0, 0, 0, 0, 33, 230, 115, 23, 203, 196, 190, 42, 235, 0, 103, 122, 214, 70, 39, 120, 168, 245, 34, 116, 185, 214, 5, 223, 37, 145, 178, 48, 39, 168, 125, 255, 0, 0, 0, 5, 0, 0, 0, 0, 0, 152, 150, 128, 0, 0, 0, 1, 0, 0, 0, 0, 111, 101, 34, 174, 82, 176, 35, 16, 118, 220, 99, 255, 149, 247, 234, 34, 226, 253, 128, 148, 62, 55, 35, 83, 2, 199, 238, 50, 175, 206, 76, 214, 0, 0, 0, 0, 33, 230, 115, 23, 203, 196, 190, 42, 235, 0, 103, 122, 214, 70, 39, 120, 168, 245, 34, 116, 185, 214, 5, 223, 37, 145, 178, 48, 39, 168, 125, 255, 0, 0, 0, 5, 0, 0, 0, 0, 0, 152, 150, 128, 0, 0, 0, 1, 0, 0, 0, 0, 132, 86, 73, 195, 209, 166, 48, 216, 180, 102, 247, 183, 39, 246, 87, 124, 180, 161, 120, 100, 105, 158, 109, 231, 86, 228, 132, 184, 29, 132, 205, 42, 0, 0, 0, 0, 33, 230, 115, 23, 203, 196, 190, 42, 235, 0, 103, 122, 214, 70, 39, 120, 168, 245, 34, 116, 185, 214, 5, 223, 37, 145, 178, 48, 39, 168, 125, 255, 0, 0, 0, 5, 0, 0, 0, 0, 0, 108, 43, 68, 0, 0, 0, 1, 0, 0, 0, 0, 209, 230, 72, 12, 24, 37, 25, 126, 46, 194, 147, 166, 11, 172, 220, 127, 96, 191, 186, 47, 60, 197, 56, 56, 85, 24, 11, 69, 213, 149, 167, 3, 0, 0, 0, 0, 33, 230, 115, 23, 203, 196, 190, 42, 235, 0, 103, 122, 214, 70, 39, 120, 168, 245, 34, 116, 185, 214, 5, 223, 37, 145, 178, 48, 39, 168, 125, 255, 0, 0, 0, 5, 0, 0, 0, 0, 0, 122, 18, 0, 0, 0, 0, 1, 0, 0, 0, 0, 245, 155, 154, 23, 94, 190, 76, 205, 141, 229, 220, 252, 106, 38, 135, 4, 20, 243, 12, 105, 108, 206, 25, 40, 63, 48, 20, 86, 36, 180, 69, 183, 0, 0, 0, 0, 33, 230, 115, 23, 203, 196, 190, 42, 235, 0, 103, 122, 214, 70, 39, 120, 168, 245, 34, 116, 185, 214, 5, 223, 37, 145, 178, 48, 39, 168, 125, 255, 0, 0, 0, 5, 0, 0, 0, 0, 1, 7, 164, 147, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
);
}
}
Loading
Loading