Add sequence to terra wormhole
Change-Id: Ic8aa508402b3c07334e059ed1b8973ccf1c1dc6d
This commit is contained in:
parent
3a20ec9b0d
commit
b177c94737
|
@ -58,7 +58,7 @@ pub fn extend_address_to_32(addr: &CanonicalAddr) -> Vec<u8> {
|
||||||
pub fn extend_string_to_32(s: &String) -> StdResult<Vec<u8>> {
|
pub fn extend_string_to_32(s: &String) -> StdResult<Vec<u8>> {
|
||||||
let bytes = s.as_bytes();
|
let bytes = s.as_bytes();
|
||||||
if bytes.len() > 32 {
|
if bytes.len() > 32 {
|
||||||
return Err(StdError::generic_err("string more than 32 "))
|
return Err(StdError::generic_err("string more than 32 "));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut result = vec![0; 32 - bytes.len()];
|
let mut result = vec![0; 32 - bytes.len()];
|
||||||
|
|
|
@ -6,11 +6,13 @@ use cosmwasm_std::{
|
||||||
use crate::byte_utils::extend_address_to_32;
|
use crate::byte_utils::extend_address_to_32;
|
||||||
use crate::byte_utils::ByteUtils;
|
use crate::byte_utils::ByteUtils;
|
||||||
use crate::error::ContractError;
|
use crate::error::ContractError;
|
||||||
use crate::msg::{GetAddressHexResponse, GetStateResponse, GuardianSetInfoResponse, HandleMsg, InitMsg, QueryMsg};
|
use crate::msg::{
|
||||||
|
GetAddressHexResponse, GetStateResponse, GuardianSetInfoResponse, HandleMsg, InitMsg, QueryMsg,
|
||||||
|
};
|
||||||
use crate::state::{
|
use crate::state::{
|
||||||
config, config_read, guardian_set_get, guardian_set_set, vaa_archive_check,
|
config, config_read, guardian_set_get, guardian_set_set, sequence_read, sequence_set,
|
||||||
ConfigInfo, GovernancePacket, GuardianAddress, GuardianSetInfo, GuardianSetUpgrade, ParsedVAA,
|
vaa_archive_check, ConfigInfo, GovernancePacket, GuardianAddress, GuardianSetInfo,
|
||||||
TransferFee,
|
GuardianSetUpgrade, ParsedVAA, TransferFee,
|
||||||
};
|
};
|
||||||
|
|
||||||
use k256::ecdsa::recoverable::Id as RecoverableId;
|
use k256::ecdsa::recoverable::Id as RecoverableId;
|
||||||
|
@ -257,18 +259,19 @@ fn handle_post_message<S: Storage, A: Api, Q: Querier>(
|
||||||
return ContractError::FeeTooLow.std_err();
|
return ContractError::FeeTooLow.std_err();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let emitter = extend_address_to_32(&deps.api.canonical_address(&env.message.sender)?);
|
||||||
|
|
||||||
|
let sequence = sequence_read(&deps.storage, emitter.as_slice());
|
||||||
|
sequence_set(&mut deps.storage, emitter.as_slice(), sequence + 1)?;
|
||||||
|
|
||||||
Ok(HandleResponse {
|
Ok(HandleResponse {
|
||||||
messages: vec![],
|
messages: vec![],
|
||||||
log: vec![
|
log: vec![
|
||||||
log("message.message", hex::encode(message)),
|
log("message.message", hex::encode(message)),
|
||||||
log(
|
log("message.sender", hex::encode(emitter)),
|
||||||
"message.sender",
|
|
||||||
hex::encode(extend_address_to_32(
|
|
||||||
&deps.api.canonical_address(&env.message.sender)?,
|
|
||||||
)),
|
|
||||||
),
|
|
||||||
log("message.chain_id", CHAIN_ID),
|
log("message.chain_id", CHAIN_ID),
|
||||||
log("message.nonce", nonce),
|
log("message.nonce", nonce),
|
||||||
|
log("message.sequence", sequence),
|
||||||
log("message.block_time", env.block.time),
|
log("message.block_time", env.block.time),
|
||||||
],
|
],
|
||||||
data: None,
|
data: None,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use cosmwasm_std::{Binary, HumanAddr, Coin};
|
use cosmwasm_std::{Binary, Coin, HumanAddr};
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -16,13 +16,8 @@ pub struct InitMsg {
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
||||||
#[serde(rename_all = "snake_case")]
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum HandleMsg {
|
pub enum HandleMsg {
|
||||||
SubmitVAA {
|
SubmitVAA { vaa: Binary },
|
||||||
vaa: Binary,
|
PostMessage { message: Binary, nonce: u32 },
|
||||||
},
|
|
||||||
PostMessage {
|
|
||||||
message: Binary,
|
|
||||||
nonce: u32
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
||||||
|
@ -31,7 +26,7 @@ pub enum QueryMsg {
|
||||||
GuardianSetInfo {},
|
GuardianSetInfo {},
|
||||||
VerifyVAA { vaa: Binary, block_time: u64 },
|
VerifyVAA { vaa: Binary, block_time: u64 },
|
||||||
GetState {},
|
GetState {},
|
||||||
QueryAddressHex { address: HumanAddr }
|
QueryAddressHex { address: HumanAddr },
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use schemars::JsonSchema;
|
use schemars::JsonSchema;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use cosmwasm_std::{Binary, CanonicalAddr, HumanAddr, StdResult, Storage, Coin, Uint128};
|
use cosmwasm_std::{Binary, CanonicalAddr, Coin, HumanAddr, StdResult, Storage, Uint128};
|
||||||
use cosmwasm_storage::{
|
use cosmwasm_storage::{
|
||||||
bucket, bucket_read, singleton, singleton_read, Bucket, ReadonlyBucket, ReadonlySingleton,
|
bucket, bucket_read, singleton, singleton_read, Bucket, ReadonlyBucket, ReadonlySingleton,
|
||||||
Singleton,
|
Singleton,
|
||||||
|
@ -14,6 +14,7 @@ use sha3::{Digest, Keccak256};
|
||||||
|
|
||||||
pub static CONFIG_KEY: &[u8] = b"config";
|
pub static CONFIG_KEY: &[u8] = b"config";
|
||||||
pub static GUARDIAN_SET_KEY: &[u8] = b"guardian_set";
|
pub static GUARDIAN_SET_KEY: &[u8] = b"guardian_set";
|
||||||
|
pub static SEQUENCE_KEY: &[u8] = b"sequence";
|
||||||
pub static WRAPPED_ASSET_KEY: &[u8] = b"wrapped_asset";
|
pub static WRAPPED_ASSET_KEY: &[u8] = b"wrapped_asset";
|
||||||
pub static WRAPPED_ASSET_ADDRESS_KEY: &[u8] = b"wrapped_asset_address";
|
pub static WRAPPED_ASSET_ADDRESS_KEY: &[u8] = b"wrapped_asset_address";
|
||||||
|
|
||||||
|
@ -37,7 +38,6 @@ pub struct ConfigInfo {
|
||||||
// Validator Action Approval(VAA) data
|
// Validator Action Approval(VAA) data
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
||||||
pub struct ParsedVAA {
|
pub struct ParsedVAA {
|
||||||
|
|
||||||
pub version: u8,
|
pub version: u8,
|
||||||
pub guardian_set_index: u32,
|
pub guardian_set_index: u32,
|
||||||
pub timestamp: u64,
|
pub timestamp: u64,
|
||||||
|
@ -46,9 +46,10 @@ pub struct ParsedVAA {
|
||||||
|
|
||||||
pub emitter_chain: u16,
|
pub emitter_chain: u16,
|
||||||
pub emitter_address: Vec<u8>,
|
pub emitter_address: Vec<u8>,
|
||||||
|
pub sequence: u64,
|
||||||
pub payload: Vec<u8>,
|
pub payload: Vec<u8>,
|
||||||
|
|
||||||
pub hash: Vec<u8>
|
pub hash: Vec<u8>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParsedVAA {
|
impl ParsedVAA {
|
||||||
|
@ -68,7 +69,8 @@ impl ParsedVAA {
|
||||||
8 uint32 nonce
|
8 uint32 nonce
|
||||||
12 uint16 emitter_chain
|
12 uint16 emitter_chain
|
||||||
14 [32]uint8 emitter_address
|
14 [32]uint8 emitter_address
|
||||||
46 []uint8 payload
|
46 uint64 sequence
|
||||||
|
54 []uint8 payload
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pub const HEADER_LEN: usize = 6;
|
pub const HEADER_LEN: usize = 6;
|
||||||
|
@ -80,7 +82,8 @@ impl ParsedVAA {
|
||||||
pub const VAA_NONCE_POS: usize = 8;
|
pub const VAA_NONCE_POS: usize = 8;
|
||||||
pub const VAA_EMITTER_CHAIN_POS: usize = 12;
|
pub const VAA_EMITTER_CHAIN_POS: usize = 12;
|
||||||
pub const VAA_EMITTER_ADDRESS_POS: usize = 14;
|
pub const VAA_EMITTER_ADDRESS_POS: usize = 14;
|
||||||
pub const VAA_PAYLOAD_POS: usize = 46;
|
pub const VAA_SEQUENCE_POS: usize = 46;
|
||||||
|
pub const VAA_PAYLOAD_POS: usize = 54;
|
||||||
|
|
||||||
// Signature data offsets in the signature block
|
// Signature data offsets in the signature block
|
||||||
pub const SIG_DATA_POS: usize = 1;
|
pub const SIG_DATA_POS: usize = 1;
|
||||||
|
@ -114,7 +117,10 @@ impl ParsedVAA {
|
||||||
let timestamp = data.get_u64(body_offset);
|
let timestamp = data.get_u64(body_offset);
|
||||||
let nonce = data.get_u32(body_offset + Self::VAA_NONCE_POS);
|
let nonce = data.get_u32(body_offset + Self::VAA_NONCE_POS);
|
||||||
let emitter_chain = data.get_u16(body_offset + Self::VAA_EMITTER_CHAIN_POS);
|
let emitter_chain = data.get_u16(body_offset + Self::VAA_EMITTER_CHAIN_POS);
|
||||||
let emitter_address = data.get_bytes32(body_offset + Self::VAA_EMITTER_ADDRESS_POS).to_vec();
|
let emitter_address = data
|
||||||
|
.get_bytes32(body_offset + Self::VAA_EMITTER_ADDRESS_POS)
|
||||||
|
.to_vec();
|
||||||
|
let sequence = data.get_u64(body_offset + Self::VAA_SEQUENCE_POS);
|
||||||
let payload = data[body_offset + Self::VAA_PAYLOAD_POS..].to_vec();
|
let payload = data[body_offset + Self::VAA_PAYLOAD_POS..].to_vec();
|
||||||
|
|
||||||
Ok(ParsedVAA {
|
Ok(ParsedVAA {
|
||||||
|
@ -125,6 +131,7 @@ impl ParsedVAA {
|
||||||
len_signers: len_signers as u8,
|
len_signers: len_signers as u8,
|
||||||
emitter_chain,
|
emitter_chain,
|
||||||
emitter_address,
|
emitter_address,
|
||||||
|
sequence,
|
||||||
payload,
|
payload,
|
||||||
hash,
|
hash,
|
||||||
})
|
})
|
||||||
|
@ -139,6 +146,7 @@ pub struct GuardianAddress {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use hex;
|
use hex;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
impl GuardianAddress {
|
impl GuardianAddress {
|
||||||
pub fn from(string: &str) -> GuardianAddress {
|
pub fn from(string: &str) -> GuardianAddress {
|
||||||
|
@ -151,7 +159,8 @@ impl GuardianAddress {
|
||||||
// Guardian set information
|
// Guardian set information
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
|
||||||
pub struct GuardianSetInfo {
|
pub struct GuardianSetInfo {
|
||||||
pub addresses: Vec<GuardianAddress>, // List of guardian addresses
|
pub addresses: Vec<GuardianAddress>,
|
||||||
|
// List of guardian addresses
|
||||||
pub expiration_time: u64, // Guardian set expiration time
|
pub expiration_time: u64, // Guardian set expiration time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,6 +201,17 @@ pub fn guardian_set_get<S: Storage>(storage: &S, index: u32) -> StdResult<Guardi
|
||||||
bucket_read(GUARDIAN_SET_KEY, storage).load(&index.to_be_bytes())
|
bucket_read(GUARDIAN_SET_KEY, storage).load(&index.to_be_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn sequence_set<S: Storage>(storage: &mut S, emitter: &[u8], sequence: u64) -> StdResult<()> {
|
||||||
|
bucket(SEQUENCE_KEY, storage).save(emitter, &sequence)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sequence_read<S: Storage>(storage: &S, emitter: &[u8]) -> u64 {
|
||||||
|
bucket_read(SEQUENCE_KEY, storage)
|
||||||
|
.load(&emitter)
|
||||||
|
.or::<u64>(Ok(0))
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn vaa_archive_add<S: Storage>(storage: &mut S, hash: &[u8]) -> StdResult<()> {
|
pub fn vaa_archive_add<S: Storage>(storage: &mut S, hash: &[u8]) -> StdResult<()> {
|
||||||
bucket(GUARDIAN_SET_KEY, storage).save(hash, &true)
|
bucket(GUARDIAN_SET_KEY, storage).save(hash, &true)
|
||||||
}
|
}
|
||||||
|
@ -219,7 +239,6 @@ pub fn wrapped_asset_address_read<S: Storage>(storage: &S) -> ReadonlyBucket<S,
|
||||||
bucket_read(WRAPPED_ASSET_ADDRESS_KEY, storage)
|
bucket_read(WRAPPED_ASSET_ADDRESS_KEY, storage)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub struct GovernancePacket {
|
pub struct GovernancePacket {
|
||||||
pub module: Vec<u8>,
|
pub module: Vec<u8>,
|
||||||
pub chain: u16,
|
pub chain: u16,
|
||||||
|
@ -239,7 +258,7 @@ impl GovernancePacket {
|
||||||
module,
|
module,
|
||||||
chain,
|
chain,
|
||||||
action,
|
action,
|
||||||
payload
|
payload,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,7 +271,6 @@ pub struct GuardianSetUpgrade {
|
||||||
|
|
||||||
impl GuardianSetUpgrade {
|
impl GuardianSetUpgrade {
|
||||||
pub fn deserialize(data: &Vec<u8>) -> StdResult<Self> {
|
pub fn deserialize(data: &Vec<u8>) -> StdResult<Self> {
|
||||||
|
|
||||||
const ADDRESS_LEN: usize = 20;
|
const ADDRESS_LEN: usize = 20;
|
||||||
|
|
||||||
let data = data.as_slice();
|
let data = data.as_slice();
|
||||||
|
@ -275,15 +293,13 @@ impl GuardianSetUpgrade {
|
||||||
|
|
||||||
let new_guardian_set = GuardianSetInfo {
|
let new_guardian_set = GuardianSetInfo {
|
||||||
addresses,
|
addresses,
|
||||||
expiration_time: 0
|
expiration_time: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
return Ok(
|
return Ok(GuardianSetUpgrade {
|
||||||
GuardianSetUpgrade {
|
|
||||||
new_guardian_set_index,
|
new_guardian_set_index,
|
||||||
new_guardian_set
|
new_guardian_set,
|
||||||
}
|
});
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,16 +317,10 @@ impl TransferFee {
|
||||||
let amount = Uint128(data.get_u128_be(32));
|
let amount = Uint128(data.get_u128_be(32));
|
||||||
let denom = match String::from_utf8(data[48..].to_vec()) {
|
let denom = match String::from_utf8(data[48..].to_vec()) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(_) => return ContractError::InvalidVAA.std_err()
|
Err(_) => return ContractError::InvalidVAA.std_err(),
|
||||||
};
|
};
|
||||||
let amount = Coin {
|
let amount = Coin { denom, amount };
|
||||||
denom,
|
Ok(TransferFee { amount, recipient })
|
||||||
amount,
|
|
||||||
};
|
|
||||||
Ok(TransferFee {
|
|
||||||
amount,
|
|
||||||
recipient
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -353,7 +363,31 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_deserialize() {
|
fn test_deserialize() {
|
||||||
let x = vec![1u8,0u8,0u8,0u8,1u8,0u8,0u8,0u8,0u8,0u8,96u8,180u8,80u8,111u8,0u8,0u8,0u8,1u8,0u8,3u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,0u8,120u8,73u8,153u8,19u8,90u8,170u8,138u8,60u8,165u8,145u8,68u8,104u8,133u8,47u8,221u8,219u8,221u8,216u8,120u8,157u8,0u8,91u8,48u8,44u8,48u8,44u8,51u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,53u8,54u8,44u8,50u8,51u8,51u8,44u8,49u8,44u8,49u8,49u8,49u8,44u8,49u8,54u8,55u8,44u8,49u8,57u8,48u8,44u8,50u8,48u8,51u8,44u8,49u8,54u8,44u8,49u8,55u8,54u8,44u8,50u8,49u8,56u8,44u8,50u8,53u8,49u8,44u8,49u8,51u8,49u8,44u8,51u8,57u8,44u8,49u8,54u8,44u8,49u8,57u8,53u8,44u8,50u8,50u8,55u8,44u8,49u8,52u8,57u8,44u8,50u8,51u8,54u8,44u8,49u8,57u8,48u8,44u8,50u8,49u8,50u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,51u8,44u8,50u8,51u8,50u8,44u8,48u8,44u8,51u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,48u8,44u8,53u8,51u8,44u8,49u8,49u8,54u8,44u8,52u8,56u8,44u8,49u8,49u8,54u8,44u8,49u8,52u8,57u8,44u8,49u8,48u8,56u8,44u8,49u8,49u8,51u8,44u8,56u8,44u8,48u8,44u8,50u8,51u8,50u8,44u8,52u8,57u8,44u8,49u8,53u8,50u8,44u8,49u8,44u8,50u8,56u8,44u8,50u8,48u8,51u8,44u8,50u8,49u8,50u8,44u8,50u8,50u8,49u8,44u8,50u8,52u8,49u8,44u8,56u8,53u8,44u8,49u8,48u8,57u8,93u8];
|
let x = vec![
|
||||||
|
1u8, 0u8, 0u8, 0u8, 1u8, 0u8, 0u8, 0u8, 0u8, 0u8, 96u8, 180u8, 80u8, 111u8, 0u8, 0u8,
|
||||||
|
0u8, 1u8, 0u8, 3u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 0u8, 120u8,
|
||||||
|
73u8, 153u8, 19u8, 90u8, 170u8, 138u8, 60u8, 165u8, 145u8, 68u8, 104u8, 133u8, 47u8,
|
||||||
|
221u8, 219u8, 221u8, 216u8, 120u8, 157u8, 0u8, 91u8, 48u8, 44u8, 48u8, 44u8, 51u8,
|
||||||
|
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8,
|
||||||
|
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 53u8, 54u8, 44u8,
|
||||||
|
50u8, 51u8, 51u8, 44u8, 49u8, 44u8, 49u8, 49u8, 49u8, 44u8, 49u8, 54u8, 55u8, 44u8,
|
||||||
|
49u8, 57u8, 48u8, 44u8, 50u8, 48u8, 51u8, 44u8, 49u8, 54u8, 44u8, 49u8, 55u8, 54u8,
|
||||||
|
44u8, 50u8, 49u8, 56u8, 44u8, 50u8, 53u8, 49u8, 44u8, 49u8, 51u8, 49u8, 44u8, 51u8,
|
||||||
|
57u8, 44u8, 49u8, 54u8, 44u8, 49u8, 57u8, 53u8, 44u8, 50u8, 50u8, 55u8, 44u8, 49u8,
|
||||||
|
52u8, 57u8, 44u8, 50u8, 51u8, 54u8, 44u8, 49u8, 57u8, 48u8, 44u8, 50u8, 49u8, 50u8,
|
||||||
|
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8,
|
||||||
|
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8,
|
||||||
|
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8,
|
||||||
|
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8,
|
||||||
|
44u8, 48u8, 44u8, 48u8, 44u8, 51u8, 44u8, 50u8, 51u8, 50u8, 44u8, 48u8, 44u8, 51u8,
|
||||||
|
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8,
|
||||||
|
44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 48u8, 44u8, 53u8, 51u8, 44u8,
|
||||||
|
49u8, 49u8, 54u8, 44u8, 52u8, 56u8, 44u8, 49u8, 49u8, 54u8, 44u8, 49u8, 52u8, 57u8,
|
||||||
|
44u8, 49u8, 48u8, 56u8, 44u8, 49u8, 49u8, 51u8, 44u8, 56u8, 44u8, 48u8, 44u8, 50u8,
|
||||||
|
51u8, 50u8, 44u8, 52u8, 57u8, 44u8, 49u8, 53u8, 50u8, 44u8, 49u8, 44u8, 50u8, 56u8,
|
||||||
|
44u8, 50u8, 48u8, 51u8, 44u8, 50u8, 49u8, 50u8, 44u8, 50u8, 50u8, 49u8, 44u8, 50u8,
|
||||||
|
52u8, 49u8, 44u8, 56u8, 53u8, 44u8, 49u8, 48u8, 57u8, 93u8,
|
||||||
|
];
|
||||||
ParsedVAA::deserialize(x.as_slice()).unwrap();
|
ParsedVAA::deserialize(x.as_slice()).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue