Add sequence to terra wormhole

Change-Id: Ic8aa508402b3c07334e059ed1b8973ccf1c1dc6d
This commit is contained in:
Hendrik Hofstadt 2021-06-28 14:45:25 +02:00
parent 3a20ec9b0d
commit b177c94737
4 changed files with 82 additions and 50 deletions

View File

@ -58,10 +58,10 @@ pub fn extend_address_to_32(addr: &CanonicalAddr) -> Vec<u8> {
pub fn extend_string_to_32(s: &String) -> StdResult<Vec<u8>> {
let bytes = s.as_bytes();
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()];
result.extend(bytes);
Ok(result)
}
}

View File

@ -6,11 +6,13 @@ use cosmwasm_std::{
use crate::byte_utils::extend_address_to_32;
use crate::byte_utils::ByteUtils;
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::{
config, config_read, guardian_set_get, guardian_set_set, vaa_archive_check,
ConfigInfo, GovernancePacket, GuardianAddress, GuardianSetInfo, GuardianSetUpgrade, ParsedVAA,
TransferFee,
config, config_read, guardian_set_get, guardian_set_set, sequence_read, sequence_set,
vaa_archive_check, ConfigInfo, GovernancePacket, GuardianAddress, GuardianSetInfo,
GuardianSetUpgrade, ParsedVAA, TransferFee,
};
use k256::ecdsa::recoverable::Id as RecoverableId;
@ -154,7 +156,7 @@ fn parse_and_verify_vaa<S: Storage>(
&data[pos + ParsedVAA::SIG_DATA_POS
..pos + ParsedVAA::SIG_DATA_POS + ParsedVAA::SIG_DATA_LEN],
)
.or_else(|_| ContractError::CannotDecodeSignature.std_err())?;
.or_else(|_| ContractError::CannotDecodeSignature.std_err())?;
let id = RecoverableId::new(data.get_u8(pos + ParsedVAA::SIG_RECOVERY_POS))
.or_else(|_| ContractError::CannotDecodeSignature.std_err())?;
let recoverable_signature = RecoverableSignature::new(&signature, id)
@ -257,18 +259,19 @@ fn handle_post_message<S: Storage, A: Api, Q: Querier>(
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 {
messages: vec![],
log: vec![
log("message.message", hex::encode(message)),
log(
"message.sender",
hex::encode(extend_address_to_32(
&deps.api.canonical_address(&env.message.sender)?,
)),
),
log("message.sender", hex::encode(emitter)),
log("message.chain_id", CHAIN_ID),
log("message.nonce", nonce),
log("message.sequence", sequence),
log("message.block_time", env.block.time),
],
data: None,

View File

@ -1,4 +1,4 @@
use cosmwasm_std::{Binary, HumanAddr, Coin};
use cosmwasm_std::{Binary, Coin, HumanAddr};
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
@ -16,13 +16,8 @@ pub struct InitMsg {
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum HandleMsg {
SubmitVAA {
vaa: Binary,
},
PostMessage {
message: Binary,
nonce: u32
},
SubmitVAA { vaa: Binary },
PostMessage { message: Binary, nonce: u32 },
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
@ -31,7 +26,7 @@ pub enum QueryMsg {
GuardianSetInfo {},
VerifyVAA { vaa: Binary, block_time: u64 },
GetState {},
QueryAddressHex { address: HumanAddr }
QueryAddressHex { address: HumanAddr },
}
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]

View File

@ -1,7 +1,7 @@
use schemars::JsonSchema;
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::{
bucket, bucket_read, singleton, singleton_read, Bucket, ReadonlyBucket, ReadonlySingleton,
Singleton,
@ -14,6 +14,7 @@ use sha3::{Digest, Keccak256};
pub static CONFIG_KEY: &[u8] = b"config";
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_ADDRESS_KEY: &[u8] = b"wrapped_asset_address";
@ -37,7 +38,6 @@ pub struct ConfigInfo {
// Validator Action Approval(VAA) data
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct ParsedVAA {
pub version: u8,
pub guardian_set_index: u32,
pub timestamp: u64,
@ -46,9 +46,10 @@ pub struct ParsedVAA {
pub emitter_chain: u16,
pub emitter_address: Vec<u8>,
pub sequence: u64,
pub payload: Vec<u8>,
pub hash: Vec<u8>
pub hash: Vec<u8>,
}
impl ParsedVAA {
@ -68,7 +69,8 @@ impl ParsedVAA {
8 uint32 nonce
12 uint16 emitter_chain
14 [32]uint8 emitter_address
46 []uint8 payload
46 uint64 sequence
54 []uint8 payload
*/
pub const HEADER_LEN: usize = 6;
@ -80,7 +82,8 @@ impl ParsedVAA {
pub const VAA_NONCE_POS: usize = 8;
pub const VAA_EMITTER_CHAIN_POS: usize = 12;
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
pub const SIG_DATA_POS: usize = 1;
@ -114,7 +117,10 @@ impl ParsedVAA {
let timestamp = data.get_u64(body_offset);
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_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();
Ok(ParsedVAA {
@ -125,6 +131,7 @@ impl ParsedVAA {
len_signers: len_signers as u8,
emitter_chain,
emitter_address,
sequence,
payload,
hash,
})
@ -139,6 +146,7 @@ pub struct GuardianAddress {
#[cfg(test)]
use hex;
#[cfg(test)]
impl GuardianAddress {
pub fn from(string: &str) -> GuardianAddress {
@ -151,8 +159,9 @@ impl GuardianAddress {
// Guardian set information
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)]
pub struct GuardianSetInfo {
pub addresses: Vec<GuardianAddress>, // List of guardian addresses
pub expiration_time: u64, // Guardian set expiration time
pub addresses: Vec<GuardianAddress>,
// List of guardian addresses
pub expiration_time: u64, // Guardian set expiration time
}
impl GuardianSetInfo {
@ -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())
}
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<()> {
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)
}
pub struct GovernancePacket {
pub module: Vec<u8>,
pub chain: u16,
@ -239,7 +258,7 @@ impl GovernancePacket {
module,
chain,
action,
payload
payload,
})
}
}
@ -252,7 +271,6 @@ pub struct GuardianSetUpgrade {
impl GuardianSetUpgrade {
pub fn deserialize(data: &Vec<u8>) -> StdResult<Self> {
const ADDRESS_LEN: usize = 20;
let data = data.as_slice();
@ -275,15 +293,13 @@ impl GuardianSetUpgrade {
let new_guardian_set = GuardianSetInfo {
addresses,
expiration_time: 0
expiration_time: 0,
};
return Ok(
GuardianSetUpgrade {
new_guardian_set_index,
new_guardian_set
}
)
return Ok(GuardianSetUpgrade {
new_guardian_set_index,
new_guardian_set,
});
}
}
@ -301,16 +317,10 @@ impl TransferFee {
let amount = Uint128(data.get_u128_be(32));
let denom = match String::from_utf8(data[48..].to_vec()) {
Ok(s) => s,
Err(_) => return ContractError::InvalidVAA.std_err()
Err(_) => return ContractError::InvalidVAA.std_err(),
};
let amount = Coin {
denom,
amount,
};
Ok(TransferFee {
amount,
recipient
})
let amount = Coin { denom, amount };
Ok(TransferFee { amount, recipient })
}
}
@ -353,7 +363,31 @@ mod tests {
#[test]
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();
}
}