[solana] Add wrong vaa tests (#1262)
* Checkpoint * Checkpoint * Cleanup * Checkpoint, debug * Go * Checkpoint * Fix * Add new error and test * Cleanup * Add another test * Keep adding errors * Another test * Add comment * Rename * Rename
This commit is contained in:
parent
4edef3a4ed
commit
2ab72d994d
|
@ -2981,6 +2981,7 @@ dependencies = [
|
|||
name = "program-simulator"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anchor-lang",
|
||||
"bincode",
|
||||
"borsh 0.10.3",
|
||||
"solana-client",
|
||||
|
|
|
@ -15,3 +15,4 @@ solana-program-test = "1.16.20"
|
|||
solana-program = "1.16.20"
|
||||
bincode = "1.3.3"
|
||||
borsh = "0.10.3"
|
||||
anchor-lang = "0.28.0"
|
||||
|
|
|
@ -2,8 +2,12 @@ use {
|
|||
borsh::BorshDeserialize,
|
||||
solana_program::{
|
||||
hash::Hash,
|
||||
instruction::Instruction,
|
||||
instruction::{
|
||||
Instruction,
|
||||
InstructionError,
|
||||
},
|
||||
native_token::LAMPORTS_PER_SOL,
|
||||
program_error::ProgramError,
|
||||
pubkey::Pubkey,
|
||||
system_instruction,
|
||||
},
|
||||
|
@ -14,11 +18,15 @@ use {
|
|||
ProgramTestBanksClientExt,
|
||||
},
|
||||
solana_sdk::{
|
||||
compute_budget,
|
||||
signature::{
|
||||
Keypair,
|
||||
Signer,
|
||||
},
|
||||
transaction::Transaction,
|
||||
transaction::{
|
||||
Transaction,
|
||||
TransactionError,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -43,15 +51,19 @@ impl ProgramSimulator {
|
|||
|
||||
/// Process a transaction containing `instruction` signed by `signers`.
|
||||
/// `payer` is used to pay for and sign the transaction.
|
||||
pub async fn process_ix(
|
||||
pub async fn process_ix_with_default_compute_limit(
|
||||
&mut self,
|
||||
instruction: Instruction,
|
||||
signers: &Vec<&Keypair>,
|
||||
payer: Option<&Keypair>,
|
||||
) -> Result<(), BanksClientError> {
|
||||
let compute_units_ixs =
|
||||
compute_budget::ComputeBudgetInstruction::set_compute_unit_limit(2000000);
|
||||
let actual_payer = payer.unwrap_or(&self.genesis_keypair);
|
||||
let mut transaction =
|
||||
Transaction::new_with_payer(&[instruction], Some(&actual_payer.pubkey()));
|
||||
let mut transaction = Transaction::new_with_payer(
|
||||
&[instruction, compute_units_ixs],
|
||||
Some(&actual_payer.pubkey()),
|
||||
);
|
||||
|
||||
let blockhash = self
|
||||
.banks_client
|
||||
|
@ -71,7 +83,8 @@ impl ProgramSimulator {
|
|||
let instruction =
|
||||
system_instruction::transfer(&self.genesis_keypair.pubkey(), to, lamports);
|
||||
|
||||
self.process_ix(instruction, &vec![], None).await
|
||||
self.process_ix_with_default_compute_limit(instruction, &vec![], None)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_funded_keypair(&mut self) -> Result<Keypair, BanksClientError> {
|
||||
|
@ -94,3 +107,10 @@ impl ProgramSimulator {
|
|||
Ok(T::deserialize(&mut &account.data[8..])?)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_transaction_error<T: Into<anchor_lang::prelude::Error>>(error: T) -> TransactionError {
|
||||
TransactionError::InstructionError(
|
||||
0,
|
||||
InstructionError::try_from(u64::from(ProgramError::from(error.into()))).unwrap(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -2,16 +2,9 @@ use anchor_lang::prelude::*;
|
|||
|
||||
#[error_code]
|
||||
pub enum ReceiverError {
|
||||
// Pyth payload errors
|
||||
#[msg("The tuple emitter chain, emitter doesn't match one of the valid data sources.")]
|
||||
InvalidDataSource,
|
||||
#[msg("The posted VAA account has the wrong owner.")]
|
||||
WrongVaaOwner,
|
||||
#[msg("The posted VAA has wrong magic number.")]
|
||||
PostedVaaHeaderWrongMagicNumber,
|
||||
#[msg("An error occurred when deserializing the VAA.")]
|
||||
DeserializeVaaFailed,
|
||||
#[msg("An error occurred when deserializing the updates.")]
|
||||
DeserializeUpdateFailed,
|
||||
#[msg("An error occurred when deserializing the message")]
|
||||
DeserializeMessageFailed,
|
||||
#[msg("Received an invalid wormhole message")]
|
||||
|
@ -20,27 +13,39 @@ pub enum ReceiverError {
|
|||
InvalidPriceUpdate,
|
||||
#[msg("This type of message is not supported currently")]
|
||||
UnsupportedMessageType,
|
||||
#[msg("The signer is not authorized to perform this governance action")]
|
||||
GovernanceAuthorityMismatch,
|
||||
#[msg("The signer is not authorized to accept the governance authority")]
|
||||
TargetGovernanceAuthorityMismatch,
|
||||
#[msg("The governance authority needs to request a transfer first")]
|
||||
NonexistentGovernanceAuthorityTransferRequest,
|
||||
#[msg("Funds are insufficient to pay the receiving fee")]
|
||||
InsufficientFunds,
|
||||
// Wormhole contract encoded vaa error (from post_updates)
|
||||
#[msg("The posted VAA account has the wrong owner.")]
|
||||
WrongVaaOwner,
|
||||
// Wormhole signatures verification errors (from post_updates_atomic)
|
||||
#[msg("An error occurred when deserializing the VAA.")]
|
||||
DeserializeVaaFailed,
|
||||
#[msg("The number of guardian signatures is below the minimum")]
|
||||
InsufficientGuardianSignatures,
|
||||
#[msg("The Guardian Set account doesn't match the PDA derivation")]
|
||||
InvalidGuardianSetPda,
|
||||
// Wormhole errors
|
||||
#[msg("Invalid VAA version")]
|
||||
InvalidVaaVersion,
|
||||
#[msg("Guardian set version in the VAA doesn't match the guardian set passed")]
|
||||
GuardianSetMismatch,
|
||||
#[msg("Guardian signature indices must be increasing")]
|
||||
InvalidGuardianOrder,
|
||||
#[msg("Guardian index exceeds the number of guardians in the set")]
|
||||
InvalidGuardianIndex,
|
||||
#[msg("A VAA signature is invalid")]
|
||||
InvalidSignature,
|
||||
#[msg("The recovered guardian public key doesn't match the guardian set")]
|
||||
InvalidGuardianKeyRecovery,
|
||||
#[msg("The guardian set account is owned by the wrong program")]
|
||||
WrongGuardianSetOwner,
|
||||
#[msg("The Guardian Set account doesn't match the PDA derivation")]
|
||||
InvalidGuardianSetPda,
|
||||
#[msg("The Guardian Set is expired")]
|
||||
GuardianSetExpired,
|
||||
// Governance errors
|
||||
#[msg("The signer is not authorized to perform this governance action")]
|
||||
GovernanceAuthorityMismatch,
|
||||
#[msg("The signer is not authorized to accept the governance authority")]
|
||||
TargetGovernanceAuthorityMismatch,
|
||||
#[msg("The governance authority needs to request a transfer first")]
|
||||
NonexistentGovernanceAuthorityTransferRequest,
|
||||
}
|
||||
|
|
|
@ -143,7 +143,7 @@ pub mod pyth_solana_receiver {
|
|||
// We do not allow for non-increasing guardian signature indices.
|
||||
let index = usize::from(sig.guardian_index());
|
||||
if let Some(last_index) = last_guardian_index {
|
||||
require!(index > last_index, ReceiverError::InvalidGuardianIndex);
|
||||
require!(index > last_index, ReceiverError::InvalidGuardianOrder);
|
||||
}
|
||||
|
||||
// Does this guardian index exist in this guardian set?
|
||||
|
@ -258,7 +258,7 @@ pub struct AuthorizeGovernanceAuthorityTransfer<'info> {
|
|||
pub struct PostUpdates<'info> {
|
||||
#[account(mut)]
|
||||
pub payer: Signer<'info>,
|
||||
#[account(owner = config.wormhole)]
|
||||
#[account(owner = config.wormhole @ ReceiverError::WrongVaaOwner)]
|
||||
/// CHECK: We aren't deserializing the VAA here but later with VaaAccount::load, which is the recommended way
|
||||
pub encoded_vaa: AccountInfo<'info>,
|
||||
#[account(seeds = [CONFIG_SEED.as_ref()], bump)]
|
||||
|
@ -281,7 +281,7 @@ pub struct PostUpdatesAtomic<'info> {
|
|||
/// CHECK: We can't use AccountVariant::<GuardianSet> here because its owner is hardcoded as the "official" Wormhole program and we want to get the wormhole address from the config.
|
||||
/// Instead we do the same steps in deserialize_guardian_set_checked.
|
||||
#[account(
|
||||
owner = config.wormhole)]
|
||||
owner = config.wormhole @ ReceiverError::WrongGuardianSetOwner)]
|
||||
pub guardian_set: AccountInfo<'info>,
|
||||
#[account(seeds = [CONFIG_SEED.as_ref()], bump)]
|
||||
pub config: Account<'info, Config>,
|
||||
|
@ -324,6 +324,12 @@ fn deserialize_guardian_set_checked(
|
|||
ReceiverError::InvalidGuardianSetPda
|
||||
);
|
||||
|
||||
let timestamp = Clock::get().map(Into::into)?;
|
||||
require!(
|
||||
guardian_set.inner().is_active(×tamp),
|
||||
ReceiverError::GuardianSetExpired
|
||||
);
|
||||
|
||||
Ok(guardian_set)
|
||||
}
|
||||
|
||||
|
|
|
@ -44,6 +44,7 @@ use {
|
|||
};
|
||||
|
||||
pub const DEFAULT_GUARDIAN_SET_INDEX: u32 = 0;
|
||||
pub const WRONG_GUARDIAN_SET_INDEX: u32 = 1;
|
||||
|
||||
pub fn default_receiver_config() -> Config {
|
||||
Config {
|
||||
|
@ -65,11 +66,20 @@ pub struct ProgramTestFixtures {
|
|||
pub encoded_vaa_addresses: Vec<Pubkey>,
|
||||
}
|
||||
|
||||
pub fn build_encoded_vaa_account_from_vaa(vaa: Vaa<&RawMessage>) -> Account {
|
||||
pub fn build_encoded_vaa_account_from_vaa(
|
||||
vaa: Vaa<&RawMessage>,
|
||||
wrong_setup_option: WrongSetupOption,
|
||||
) -> Account {
|
||||
let encoded_vaa_data = (
|
||||
<EncodedVaa as anchor_lang::Discriminator>::DISCRIMINATOR,
|
||||
Header {
|
||||
status: ProcessingStatus::Verified,
|
||||
status: {
|
||||
if matches!(wrong_setup_option, WrongSetupOption::UnverifiedEncodedVaa) {
|
||||
ProcessingStatus::Writing
|
||||
} else {
|
||||
ProcessingStatus::Verified
|
||||
}
|
||||
},
|
||||
write_authority: Pubkey::new_unique(),
|
||||
version: 1,
|
||||
},
|
||||
|
@ -87,9 +97,15 @@ pub fn build_encoded_vaa_account_from_vaa(vaa: Vaa<&RawMessage>) -> Account {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn build_guardian_set_account() -> Account {
|
||||
pub fn build_guardian_set_account(wrong_setup_option: WrongSetupOption) -> Account {
|
||||
let guardian_set = GuardianSet {
|
||||
index: DEFAULT_GUARDIAN_SET_INDEX,
|
||||
index: {
|
||||
if matches!(wrong_setup_option, WrongSetupOption::GuardianSetWrongIndex) {
|
||||
WRONG_GUARDIAN_SET_INDEX
|
||||
} else {
|
||||
DEFAULT_GUARDIAN_SET_INDEX
|
||||
}
|
||||
},
|
||||
keys: dummy_guardians()
|
||||
.iter()
|
||||
.map(|x| {
|
||||
|
@ -101,7 +117,14 @@ pub fn build_guardian_set_account() -> Account {
|
|||
})
|
||||
.collect::<Vec<[u8; 20]>>(),
|
||||
creation_time: 0.into(),
|
||||
expiration_time: 0.into(),
|
||||
expiration_time: {
|
||||
if matches!(wrong_setup_option, WrongSetupOption::GuardianSetExpired) {
|
||||
1
|
||||
} else {
|
||||
0
|
||||
}
|
||||
}
|
||||
.into(),
|
||||
};
|
||||
|
||||
let guardian_set_data = (
|
||||
|
@ -119,12 +142,24 @@ pub fn build_guardian_set_account() -> Account {
|
|||
rent_epoch: 0,
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum WrongSetupOption {
|
||||
None,
|
||||
GuardianSetExpired,
|
||||
GuardianSetWrongIndex,
|
||||
UnverifiedEncodedVaa,
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup to test the Pyth Receiver. The return values are a tuple composed of :
|
||||
* - The program simulator, which is used to send transactions
|
||||
* - The pubkeys of the encoded VAA accounts corresponding to the VAAs passed as argument, these accounts are prepopulated and can be used to test post_updates
|
||||
*/
|
||||
pub async fn setup_pyth_receiver(vaas: Vec<Vaa<&RawMessage>>) -> ProgramTestFixtures {
|
||||
pub async fn setup_pyth_receiver(
|
||||
vaas: Vec<Vaa<&RawMessage>>,
|
||||
wrong_setup_option: WrongSetupOption,
|
||||
) -> ProgramTestFixtures {
|
||||
let mut program_test = ProgramTest::default();
|
||||
program_test.add_program("pyth_solana_receiver", ID, None);
|
||||
|
||||
|
@ -132,11 +167,14 @@ pub async fn setup_pyth_receiver(vaas: Vec<Vaa<&RawMessage>>) -> ProgramTestFixt
|
|||
for vaa in vaas {
|
||||
let encoded_vaa_address = Pubkey::new_unique();
|
||||
encoded_vaa_addresses.push(encoded_vaa_address);
|
||||
program_test.add_account(encoded_vaa_address, build_encoded_vaa_account_from_vaa(vaa));
|
||||
program_test.add_account(
|
||||
encoded_vaa_address,
|
||||
build_encoded_vaa_account_from_vaa(vaa, wrong_setup_option),
|
||||
);
|
||||
}
|
||||
program_test.add_account(
|
||||
get_guardian_set_address(BRIDGE_ID, DEFAULT_GUARDIAN_SET_INDEX),
|
||||
build_guardian_set_account(),
|
||||
build_guardian_set_account(wrong_setup_option),
|
||||
);
|
||||
|
||||
let mut program_simulator = ProgramSimulator::start_from_program_test(program_test).await;
|
||||
|
@ -145,7 +183,7 @@ pub async fn setup_pyth_receiver(vaas: Vec<Vaa<&RawMessage>>) -> ProgramTestFixt
|
|||
let setup_keypair: Keypair = program_simulator.get_funded_keypair().await.unwrap();
|
||||
|
||||
program_simulator
|
||||
.process_ix(
|
||||
.process_ix_with_default_compute_limit(
|
||||
Initialize::populate(&setup_keypair.pubkey(), initial_config.clone()),
|
||||
&vec![&setup_keypair],
|
||||
None,
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
use {
|
||||
crate::common::WrongSetupOption,
|
||||
common::{
|
||||
setup_pyth_receiver,
|
||||
ProgramTestFixtures,
|
||||
},
|
||||
program_simulator::into_transaction_error,
|
||||
pyth_solana_receiver::{
|
||||
error::ReceiverError,
|
||||
instruction::PostUpdates,
|
||||
sdk::deserialize_accumulator_update_data,
|
||||
state::price_update::{
|
||||
|
@ -18,6 +21,7 @@ use {
|
|||
create_dummy_price_feed_message,
|
||||
},
|
||||
},
|
||||
solana_program::pubkey::Pubkey,
|
||||
solana_sdk::{
|
||||
signature::Keypair,
|
||||
signer::Signer,
|
||||
|
@ -38,14 +42,18 @@ async fn test_post_updates() {
|
|||
let ProgramTestFixtures {
|
||||
mut program_simulator,
|
||||
encoded_vaa_addresses,
|
||||
} = setup_pyth_receiver(vec![serde_wormhole::from_slice(&vaa).unwrap()]).await;
|
||||
} = setup_pyth_receiver(
|
||||
vec![serde_wormhole::from_slice(&vaa).unwrap()],
|
||||
WrongSetupOption::None,
|
||||
)
|
||||
.await;
|
||||
|
||||
let poster = program_simulator.get_funded_keypair().await.unwrap();
|
||||
let price_update_keypair = Keypair::new();
|
||||
|
||||
// post one update
|
||||
program_simulator
|
||||
.process_ix(
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdates::populate(
|
||||
poster.pubkey(),
|
||||
encoded_vaa_addresses[0],
|
||||
|
@ -76,7 +84,7 @@ async fn test_post_updates() {
|
|||
|
||||
// post another update to the same account
|
||||
program_simulator
|
||||
.process_ix(
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdates::populate(
|
||||
poster.pubkey(),
|
||||
encoded_vaa_addresses[0],
|
||||
|
@ -105,3 +113,79 @@ async fn test_post_updates() {
|
|||
feed_2
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_post_updates_wrong_encoded_vaa_owner() {
|
||||
let feed_1 = create_dummy_price_feed_message(100);
|
||||
let feed_2 = create_dummy_price_feed_message(200);
|
||||
let message = create_accumulator_message(&[feed_1, feed_2], &[feed_1, feed_2], false);
|
||||
let (vaa, merkle_price_updates) = deserialize_accumulator_update_data(message).unwrap();
|
||||
|
||||
let ProgramTestFixtures {
|
||||
mut program_simulator,
|
||||
encoded_vaa_addresses: _,
|
||||
} = setup_pyth_receiver(
|
||||
vec![serde_wormhole::from_slice(&vaa).unwrap()],
|
||||
WrongSetupOption::None,
|
||||
)
|
||||
.await;
|
||||
|
||||
let poster = program_simulator.get_funded_keypair().await.unwrap();
|
||||
let price_update_keypair = Keypair::new();
|
||||
|
||||
assert_eq!(
|
||||
program_simulator
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdates::populate(
|
||||
poster.pubkey(),
|
||||
Pubkey::new_unique(), // Random pubkey instead of the encoded VAA address
|
||||
price_update_keypair.pubkey(),
|
||||
merkle_price_updates[0].clone(),
|
||||
),
|
||||
&vec![&poster, &price_update_keypair],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap_err()
|
||||
.unwrap(),
|
||||
into_transaction_error(ReceiverError::WrongVaaOwner)
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_post_updates_wrong_setup() {
|
||||
let feed_1 = create_dummy_price_feed_message(100);
|
||||
let feed_2 = create_dummy_price_feed_message(200);
|
||||
let message = create_accumulator_message(&[feed_1, feed_2], &[feed_1, feed_2], false);
|
||||
let (vaa, merkle_price_updates) = deserialize_accumulator_update_data(message).unwrap();
|
||||
|
||||
let ProgramTestFixtures {
|
||||
mut program_simulator,
|
||||
encoded_vaa_addresses,
|
||||
} = setup_pyth_receiver(
|
||||
vec![serde_wormhole::from_slice(&vaa).unwrap()],
|
||||
WrongSetupOption::UnverifiedEncodedVaa,
|
||||
)
|
||||
.await;
|
||||
|
||||
let poster = program_simulator.get_funded_keypair().await.unwrap();
|
||||
let price_update_keypair = Keypair::new();
|
||||
|
||||
assert_eq!(
|
||||
program_simulator
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdates::populate(
|
||||
poster.pubkey(),
|
||||
encoded_vaa_addresses[0],
|
||||
price_update_keypair.pubkey(),
|
||||
merkle_price_updates[0].clone(),
|
||||
),
|
||||
&vec![&poster, &price_update_keypair],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap_err()
|
||||
.unwrap(),
|
||||
into_transaction_error(wormhole_core_bridge_solana::error::CoreBridgeError::UnverifiedVaa)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,12 +1,20 @@
|
|||
use {
|
||||
crate::common::DEFAULT_GUARDIAN_SET_INDEX,
|
||||
crate::common::{
|
||||
WrongSetupOption,
|
||||
DEFAULT_GUARDIAN_SET_INDEX,
|
||||
},
|
||||
common::{
|
||||
setup_pyth_receiver,
|
||||
ProgramTestFixtures,
|
||||
},
|
||||
program_simulator::into_transaction_error,
|
||||
pyth_solana_receiver::{
|
||||
error::ReceiverError,
|
||||
instruction::PostUpdatesAtomic,
|
||||
sdk::deserialize_accumulator_update_data,
|
||||
sdk::{
|
||||
deserialize_accumulator_update_data,
|
||||
get_guardian_set_address,
|
||||
},
|
||||
state::price_update::{
|
||||
PriceUpdateV1,
|
||||
VerificationLevel,
|
||||
|
@ -20,11 +28,13 @@ use {
|
|||
trim_vaa_signatures,
|
||||
},
|
||||
},
|
||||
serde_wormhole::RawMessage,
|
||||
solana_sdk::{
|
||||
signature::Keypair,
|
||||
signer::Signer,
|
||||
},
|
||||
wormhole_core_bridge_solana::ID as BRIDGE_ID,
|
||||
wormhole_sdk::Vaa,
|
||||
};
|
||||
|
||||
mod common;
|
||||
|
@ -45,14 +55,14 @@ async fn test_post_updates_atomic() {
|
|||
let ProgramTestFixtures {
|
||||
mut program_simulator,
|
||||
encoded_vaa_addresses: _,
|
||||
} = setup_pyth_receiver(vec![]).await;
|
||||
} = setup_pyth_receiver(vec![], WrongSetupOption::None).await;
|
||||
|
||||
let poster = program_simulator.get_funded_keypair().await.unwrap();
|
||||
let price_update_keypair = Keypair::new();
|
||||
|
||||
// post one update atomically
|
||||
program_simulator
|
||||
.process_ix(
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdatesAtomic::populate(
|
||||
poster.pubkey(),
|
||||
price_update_keypair.pubkey(),
|
||||
|
@ -85,7 +95,7 @@ async fn test_post_updates_atomic() {
|
|||
|
||||
// post another update to the same account
|
||||
program_simulator
|
||||
.process_ix(
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdatesAtomic::populate(
|
||||
poster.pubkey(),
|
||||
price_update_keypair.pubkey(),
|
||||
|
@ -116,3 +126,293 @@ async fn test_post_updates_atomic() {
|
|||
feed_2
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_post_updates_atomic_wrong_vaa() {
|
||||
let feed_1 = create_dummy_price_feed_message(100);
|
||||
let feed_2 = create_dummy_price_feed_message(200);
|
||||
let message = create_accumulator_message(&[feed_1, feed_2], &[feed_1, feed_2], false);
|
||||
let (vaa, merkle_price_updates) = deserialize_accumulator_update_data(message).unwrap();
|
||||
|
||||
let ProgramTestFixtures {
|
||||
mut program_simulator,
|
||||
encoded_vaa_addresses: _,
|
||||
} = setup_pyth_receiver(vec![], WrongSetupOption::None).await;
|
||||
|
||||
let poster = program_simulator.get_funded_keypair().await.unwrap();
|
||||
let price_update_keypair = Keypair::new();
|
||||
|
||||
let mut vaa_buffer_copy: Vec<u8> = vaa.clone();
|
||||
// Mess up with the length of signatures
|
||||
vaa_buffer_copy[5] = 255;
|
||||
assert_eq!(
|
||||
program_simulator
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdatesAtomic::populate(
|
||||
poster.pubkey(),
|
||||
price_update_keypair.pubkey(),
|
||||
BRIDGE_ID,
|
||||
DEFAULT_GUARDIAN_SET_INDEX,
|
||||
vaa_buffer_copy,
|
||||
merkle_price_updates[0].clone(),
|
||||
),
|
||||
&vec![&poster, &price_update_keypair],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap_err()
|
||||
.unwrap(),
|
||||
into_transaction_error(ReceiverError::DeserializeVaaFailed)
|
||||
);
|
||||
|
||||
let vaa_wrong_num_signatures = serde_wormhole::to_vec(&trim_vaa_signatures(
|
||||
serde_wormhole::from_slice(&vaa).unwrap(),
|
||||
4,
|
||||
))
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
program_simulator
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdatesAtomic::populate(
|
||||
poster.pubkey(),
|
||||
price_update_keypair.pubkey(),
|
||||
BRIDGE_ID,
|
||||
DEFAULT_GUARDIAN_SET_INDEX,
|
||||
vaa_wrong_num_signatures.clone(),
|
||||
merkle_price_updates[0].clone(),
|
||||
),
|
||||
&vec![&poster, &price_update_keypair],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap_err()
|
||||
.unwrap(),
|
||||
into_transaction_error(ReceiverError::InsufficientGuardianSignatures)
|
||||
);
|
||||
|
||||
|
||||
let mut vaa_copy: Vaa<&RawMessage> = serde_wormhole::from_slice(&vaa).unwrap();
|
||||
vaa_copy.version = 0;
|
||||
|
||||
assert_eq!(
|
||||
program_simulator
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdatesAtomic::populate(
|
||||
poster.pubkey(),
|
||||
price_update_keypair.pubkey(),
|
||||
BRIDGE_ID,
|
||||
DEFAULT_GUARDIAN_SET_INDEX,
|
||||
serde_wormhole::to_vec(&vaa_copy).unwrap(),
|
||||
merkle_price_updates[0].clone(),
|
||||
),
|
||||
&vec![&poster, &price_update_keypair],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap_err()
|
||||
.unwrap(),
|
||||
into_transaction_error(ReceiverError::InvalidVaaVersion)
|
||||
);
|
||||
|
||||
let mut vaa_copy: Vaa<&RawMessage> = serde_wormhole::from_slice(&vaa).unwrap();
|
||||
vaa_copy.guardian_set_index = 1;
|
||||
|
||||
assert_eq!(
|
||||
program_simulator
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdatesAtomic::populate(
|
||||
poster.pubkey(),
|
||||
price_update_keypair.pubkey(),
|
||||
BRIDGE_ID,
|
||||
DEFAULT_GUARDIAN_SET_INDEX,
|
||||
serde_wormhole::to_vec(&vaa_copy).unwrap(),
|
||||
merkle_price_updates[0].clone(),
|
||||
),
|
||||
&vec![&poster, &price_update_keypair],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap_err()
|
||||
.unwrap(),
|
||||
into_transaction_error(ReceiverError::GuardianSetMismatch)
|
||||
);
|
||||
|
||||
let mut vaa_copy: Vaa<&RawMessage> = serde_wormhole::from_slice(&vaa).unwrap();
|
||||
vaa_copy.signatures[0] = vaa_copy.signatures[1];
|
||||
|
||||
assert_eq!(
|
||||
program_simulator
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdatesAtomic::populate(
|
||||
poster.pubkey(),
|
||||
price_update_keypair.pubkey(),
|
||||
BRIDGE_ID,
|
||||
DEFAULT_GUARDIAN_SET_INDEX,
|
||||
serde_wormhole::to_vec(&vaa_copy).unwrap(),
|
||||
merkle_price_updates[0].clone(),
|
||||
),
|
||||
&vec![&poster, &price_update_keypair],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap_err()
|
||||
.unwrap(),
|
||||
into_transaction_error(ReceiverError::InvalidGuardianOrder)
|
||||
);
|
||||
|
||||
|
||||
let mut vaa_copy: Vaa<&RawMessage> = serde_wormhole::from_slice(&vaa).unwrap();
|
||||
vaa_copy.signatures[0].index = 20;
|
||||
|
||||
assert_eq!(
|
||||
program_simulator
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdatesAtomic::populate(
|
||||
poster.pubkey(),
|
||||
price_update_keypair.pubkey(),
|
||||
BRIDGE_ID,
|
||||
DEFAULT_GUARDIAN_SET_INDEX,
|
||||
serde_wormhole::to_vec(&vaa_copy).unwrap(),
|
||||
merkle_price_updates[0].clone(),
|
||||
),
|
||||
&vec![&poster, &price_update_keypair],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap_err()
|
||||
.unwrap(),
|
||||
into_transaction_error(ReceiverError::InvalidGuardianIndex)
|
||||
);
|
||||
|
||||
let mut vaa_copy: Vaa<&RawMessage> = serde_wormhole::from_slice(&vaa).unwrap();
|
||||
vaa_copy.signatures[0].signature[64] = 5;
|
||||
|
||||
assert_eq!(
|
||||
program_simulator
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdatesAtomic::populate(
|
||||
poster.pubkey(),
|
||||
price_update_keypair.pubkey(),
|
||||
BRIDGE_ID,
|
||||
DEFAULT_GUARDIAN_SET_INDEX,
|
||||
serde_wormhole::to_vec(&vaa_copy).unwrap(),
|
||||
merkle_price_updates[0].clone(),
|
||||
),
|
||||
&vec![&poster, &price_update_keypair],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap_err()
|
||||
.unwrap(),
|
||||
into_transaction_error(ReceiverError::InvalidSignature)
|
||||
);
|
||||
|
||||
|
||||
let mut vaa_copy: Vaa<&RawMessage> = serde_wormhole::from_slice(&vaa).unwrap();
|
||||
vaa_copy.signatures[0].signature = vaa_copy.signatures[1].signature;
|
||||
|
||||
assert_eq!(
|
||||
program_simulator
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdatesAtomic::populate(
|
||||
poster.pubkey(),
|
||||
price_update_keypair.pubkey(),
|
||||
BRIDGE_ID,
|
||||
DEFAULT_GUARDIAN_SET_INDEX,
|
||||
serde_wormhole::to_vec(&vaa_copy).unwrap(),
|
||||
merkle_price_updates[0].clone(),
|
||||
),
|
||||
&vec![&poster, &price_update_keypair],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap_err()
|
||||
.unwrap(),
|
||||
into_transaction_error(ReceiverError::InvalidGuardianKeyRecovery)
|
||||
);
|
||||
|
||||
let mut wrong_instruction = PostUpdatesAtomic::populate(
|
||||
poster.pubkey(),
|
||||
price_update_keypair.pubkey(),
|
||||
BRIDGE_ID,
|
||||
DEFAULT_GUARDIAN_SET_INDEX,
|
||||
vaa.clone(),
|
||||
merkle_price_updates[0].clone(),
|
||||
);
|
||||
|
||||
let wrong_guardian_set = get_guardian_set_address(BRIDGE_ID, 1);
|
||||
wrong_instruction.accounts[1].pubkey = wrong_guardian_set;
|
||||
assert_eq!(
|
||||
program_simulator
|
||||
.process_ix_with_default_compute_limit(
|
||||
wrong_instruction,
|
||||
&vec![&poster, &price_update_keypair],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap_err()
|
||||
.unwrap(),
|
||||
into_transaction_error(ReceiverError::WrongGuardianSetOwner)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_post_updates_atomic_wrong_setup() {
|
||||
let feed_1 = create_dummy_price_feed_message(100);
|
||||
let feed_2 = create_dummy_price_feed_message(200);
|
||||
let message = create_accumulator_message(&[feed_1, feed_2], &[feed_1, feed_2], false);
|
||||
let (vaa, merkle_price_updates) = deserialize_accumulator_update_data(message).unwrap();
|
||||
let price_update_keypair = Keypair::new();
|
||||
|
||||
let ProgramTestFixtures {
|
||||
mut program_simulator,
|
||||
encoded_vaa_addresses: _,
|
||||
} = setup_pyth_receiver(vec![], WrongSetupOption::GuardianSetWrongIndex).await;
|
||||
let poster: Keypair = program_simulator.get_funded_keypair().await.unwrap();
|
||||
assert_eq!(
|
||||
program_simulator
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdatesAtomic::populate(
|
||||
poster.pubkey(),
|
||||
price_update_keypair.pubkey(),
|
||||
BRIDGE_ID,
|
||||
DEFAULT_GUARDIAN_SET_INDEX,
|
||||
vaa.clone(),
|
||||
merkle_price_updates[0].clone(),
|
||||
),
|
||||
&vec![&poster, &price_update_keypair],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap_err()
|
||||
.unwrap(),
|
||||
into_transaction_error(ReceiverError::InvalidGuardianSetPda)
|
||||
);
|
||||
|
||||
|
||||
let ProgramTestFixtures {
|
||||
mut program_simulator,
|
||||
encoded_vaa_addresses: _,
|
||||
} = setup_pyth_receiver(vec![], WrongSetupOption::GuardianSetExpired).await;
|
||||
let poster = program_simulator.get_funded_keypair().await.unwrap();
|
||||
assert_eq!(
|
||||
program_simulator
|
||||
.process_ix_with_default_compute_limit(
|
||||
PostUpdatesAtomic::populate(
|
||||
poster.pubkey(),
|
||||
price_update_keypair.pubkey(),
|
||||
BRIDGE_ID,
|
||||
DEFAULT_GUARDIAN_SET_INDEX,
|
||||
vaa.clone(),
|
||||
merkle_price_updates[0].clone(),
|
||||
),
|
||||
&vec![&poster, &price_update_keypair],
|
||||
None,
|
||||
)
|
||||
.await
|
||||
.unwrap_err()
|
||||
.unwrap(),
|
||||
into_transaction_error(ReceiverError::GuardianSetExpired)
|
||||
);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue