Skip to content

Commit

Permalink
fix(target_chains/solana): use find_program_address on initialize
Browse files Browse the repository at this point in the history
  • Loading branch information
Riateche committed Oct 3, 2024
1 parent f8ebeb6 commit a82e372
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use {
validate_authority,
validate_buffer,
validate_config,
validate_publisher_config,
validate_publisher_config_for_init,
validate_system,
},
},
Expand Down Expand Up @@ -51,12 +51,11 @@ pub fn initialize_publisher(
let first_account = accounts.next();
let config = validate_config(accounts.next(), args.config_bump, program_id, false)?;
let authority = validate_authority(first_account, config)?;
let publisher_config = validate_publisher_config(
let publisher_config = validate_publisher_config_for_init(
accounts.next(),
args.publisher_config_bump,
&args.publisher.into(),
program_id,
true,
)?;
let buffer = validate_buffer(accounts.next(), program_id)?;
let system = validate_system(accounts.next())?;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use {
validate::{
validate_buffer,
validate_publisher,
validate_publisher_config,
validate_publisher_config_for_access,
},
},
solana_program::{
Expand Down Expand Up @@ -39,17 +39,22 @@ pub fn submit_prices(
) -> ProgramResult {
let mut accounts = accounts.iter();
let publisher = validate_publisher(accounts.next())?;
let publisher_config = validate_publisher_config(
let publisher_config = validate_publisher_config_for_access(
accounts.next(),
args.publisher_config_bump,
publisher.key,
program_id,
false,
)?;
let buffer = validate_buffer(accounts.next(), program_id)?;

let publisher_config_data = publisher_config.data.borrow();
let publisher_config = publisher_config::read(*publisher_config_data)?;
// Required to ensure that `find_program_address` returned the same account as
// `create_program_address` in `initialize_publisher`.
ensure!(
ProgramError::InvalidArgument,
sol_memcmp(&publisher.key.to_bytes(), &publisher_config.publisher, 32) == 0
);
ensure!(
ProgramError::InvalidArgument,
sol_memcmp(&buffer.key.to_bytes(), &publisher_config.buffer_account, 32) == 0
Expand Down
37 changes: 30 additions & 7 deletions target_chains/solana/programs/pyth-price-store/src/validate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ pub fn validate_config<'a, 'b>(
require_writable: bool,
) -> Result<&'b AccountInfo<'a>, ProgramError> {
let config = account.ok_or(ProgramError::NotEnoughAccountKeys)?;
let config_pda = Pubkey::create_program_address(&[CONFIG_SEED.as_bytes(), &[bump]], program_id)
.map_err(|_| ProgramError::InvalidInstructionData)?;
let (config_pda, expected_bump) =
Pubkey::find_program_address(&[CONFIG_SEED.as_bytes()], program_id);
ensure!(ProgramError::InvalidInstructionData, bump == expected_bump);
ensure!(
ProgramError::InvalidArgument,
pubkey_eq(config.key, &config_pda)
Expand All @@ -85,14 +86,17 @@ pub fn validate_authority<'a, 'b>(
Ok(authority)
}

pub fn validate_publisher_config<'a, 'b>(
pub fn validate_publisher_config_for_access<'a, 'b>(
account: Option<&'b AccountInfo<'a>>,
bump: u8,
publisher: &Pubkey,
program_id: &Pubkey,
require_writable: bool,
) -> Result<&'b AccountInfo<'a>, ProgramError> {
let publisher_config = account.ok_or(ProgramError::NotEnoughAccountKeys)?;
// We use `create_program_address` to make the `submit_prices` instruction cheaper.
// `find_program_address` is used in `initialize_publisher`, so we'll always have
// only one publisher config per publisher. As long as we check the publisher key
// stored in the account in `submit_prices`, it should be safe.
let publisher_config_pda = Pubkey::create_program_address(
&[
PUBLISHER_CONFIG_SEED.as_bytes(),
Expand All @@ -102,9 +106,28 @@ pub fn validate_publisher_config<'a, 'b>(
program_id,
)
.map_err(|_| ProgramError::InvalidInstructionData)?;
if require_writable {
ensure!(ProgramError::InvalidArgument, publisher_config.is_writable);
}
ensure!(
ProgramError::MissingRequiredSignature,
pubkey_eq(publisher_config.key, &publisher_config_pda)
);
Ok(publisher_config)
}

pub fn validate_publisher_config_for_init<'a, 'b>(
account: Option<&'b AccountInfo<'a>>,
bump: u8,
publisher: &Pubkey,
program_id: &Pubkey,
) -> Result<&'b AccountInfo<'a>, ProgramError> {
let publisher_config = account.ok_or(ProgramError::NotEnoughAccountKeys)?;
// We use `find_program_address` to guarantee that only one publisher_config
// is created per publisher.
let (publisher_config_pda, expected_bump) = Pubkey::find_program_address(
&[PUBLISHER_CONFIG_SEED.as_bytes(), &publisher.to_bytes()],
program_id,
);
ensure!(ProgramError::InvalidInstructionData, bump == expected_bump);
ensure!(ProgramError::InvalidArgument, publisher_config.is_writable);
ensure!(
ProgramError::MissingRequiredSignature,
pubkey_eq(publisher_config.key, &publisher_config_pda)
Expand Down

0 comments on commit a82e372

Please sign in to comment.