Skip to content

Commit

Permalink
Checkpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
guibescos committed Jan 30, 2024
1 parent 422c2db commit 8e810fc
Show file tree
Hide file tree
Showing 6 changed files with 214 additions and 7 deletions.
1 change: 1 addition & 0 deletions target_chains/solana/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions target_chains/solana/program_simulator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
27 changes: 23 additions & 4 deletions target_chains/solana/program_simulator/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand All @@ -14,11 +18,15 @@ use {
ProgramTestBanksClientExt,
},
solana_sdk::{
compute_budget,
signature::{
Keypair,
Signer,
},
transaction::Transaction,
transaction::{
Transaction,
TransactionError,
},
},
};

Expand Down Expand Up @@ -49,9 +57,13 @@ impl ProgramSimulator {
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
Expand Down Expand Up @@ -94,3 +106,10 @@ impl ProgramSimulator {
Ok(T::deserialize(&mut &account.data[8..])?)
}
}

pub fn into_transation_error<T: Into<anchor_lang::prelude::Error>>(error: T) -> TransactionError {
TransactionError::InstructionError(
0,
InstructionError::try_from(u64::from(ProgramError::from(error.into()))).unwrap(),
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,6 @@ pub enum ReceiverError {
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,
}
4 changes: 2 additions & 2 deletions target_chains/solana/programs/pyth-solana-receiver/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand All @@ -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>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ use {
setup_pyth_receiver,
ProgramTestFixtures,
},
program_simulator::into_transation_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,
Expand All @@ -30,11 +35,13 @@ use {
>>>>>>> c6431163 (Go)
},
},
serde_wormhole::RawMessage,
solana_sdk::{
signature::Keypair,
signer::Signer,
},
wormhole_core_bridge_solana::ID as BRIDGE_ID,
wormhole_sdk::Vaa,
};

mod common;
Expand Down Expand Up @@ -131,3 +138,180 @@ 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![]).await;

let poster = program_simulator.get_funded_keypair().await.unwrap();
let price_update_keypair = Keypair::new();

let vaa_wrong_num_signatures = trim_vaa_signatures(vaa.clone(), 4);
assert_eq!(
program_simulator
.process_ix(
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_transation_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(
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_transation_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(
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_transation_error(ReceiverError::GuardianSetMismatch)
);

let mut vaa_copy: Vaa<&RawMessage> = serde_wormhole::from_slice(&vaa).unwrap();
vaa_copy.signatures[0].index = 20;

assert_eq!(
program_simulator
.process_ix(
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_transation_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(
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_transation_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(
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_transation_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(
wrong_instruction,
&vec![&poster, &price_update_keypair],
None,
)
.await
.unwrap_err()
.unwrap(),
into_transation_error(ReceiverError::WrongGuardianSetOwner)
);
}

0 comments on commit 8e810fc

Please sign in to comment.