Skip to content

Commit 895eb59

Browse files
authored
Update program upgrade authority check to use PDA (#313)
* Update authority check to use PDA * Format * Update comments
1 parent 881b633 commit 895eb59

File tree

3 files changed

+22
-39
lines changed

3 files changed

+22
-39
lines changed

program/rust/src/processor/upd_permissions.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -39,21 +39,16 @@ pub fn upd_permissions(
3939
accounts: &[AccountInfo],
4040
instruction_data: &[u8],
4141
) -> ProgramResult {
42-
let [funding_account, program_account, programdata_account, permissions_account, system_program] =
43-
match accounts {
44-
[v, w, x, y, z] => Ok([v, w, x, y, z]),
45-
_ => Err(OracleError::InvalidNumberOfAccounts),
46-
}?;
42+
let [funding_account, programdata_account, permissions_account, system_program] = match accounts
43+
{
44+
[w, x, y, z] => Ok([w, x, y, z]),
45+
_ => Err(OracleError::InvalidNumberOfAccounts),
46+
}?;
4747

4848
let cmd_args = load::<UpdPermissionsArgs>(instruction_data)?;
4949

5050
check_valid_funding_account(funding_account)?;
51-
check_is_upgrade_authority_for_program(
52-
funding_account,
53-
program_account,
54-
programdata_account,
55-
program_id,
56-
)?;
51+
check_is_upgrade_authority_for_program(funding_account, programdata_account, program_id)?;
5752

5853
let (permission_pda_address, bump_seed) =
5954
Pubkey::find_program_address(&[PERMISSIONS_SEED.as_bytes()], program_id);

program/rust/src/tests/pyth_simulator.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,10 @@ impl PythSimulator {
8686

8787
let mut program_test = ProgramTest::default();
8888
let program_key = Pubkey::new_unique();
89-
let programdata_key = Pubkey::new_unique();
89+
// This PDA is the actual address in the real world
90+
// https://docs.rs/solana-program/1.6.4/solana_program/bpf_loader_upgradeable/index.html
91+
let (programdata_key, _) =
92+
Pubkey::find_program_address(&[&program_key.to_bytes()], &bpf_loader_upgradeable::id());
9093

9194
let upgrade_authority_keypair = Keypair::new();
9295

@@ -368,7 +371,6 @@ impl PythSimulator {
368371
bytes_of(&cmd_args),
369372
vec![
370373
AccountMeta::new(payer.pubkey(), true),
371-
AccountMeta::new_readonly(self.program_id, false),
372374
AccountMeta::new_readonly(self.programdata_id, false),
373375
AccountMeta::new(permissions_pubkey, false),
374376
AccountMeta::new_readonly(system_program::id(), false),

program/rust/src/utils.rs

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ use {
2020
num_traits::FromPrimitive,
2121
solana_program::{
2222
account_info::AccountInfo,
23-
bpf_loader_upgradeable::UpgradeableLoaderState,
23+
bpf_loader_upgradeable::{
24+
self,
25+
UpgradeableLoaderState,
26+
},
2427
program::invoke,
2528
program_error::ProgramError,
2629
pubkey::Pubkey,
@@ -208,45 +211,28 @@ pub fn is_component_update(cmd_args: &UpdPriceArgs) -> Result<bool, OracleError>
208211
}
209212

210213

211-
/// These 3 accounts need to get passed to make sure that the upgrade authority is signing the
212-
/// transaction
213-
/// - `program_account` is the program at address `program_id`. It just contains a pointer to the
214-
/// `programdata_account`
215-
/// - `programdata_account` has an `upgrade_authority_address` field that needs to match
216-
/// `upgrade_authority.key`
214+
/// Check that `programdata_account` is actually the buffer for `program_id`.
215+
/// Check that the authority in `programdata_account` matches `upgrade_authority_account`.
217216
pub fn check_is_upgrade_authority_for_program(
218217
upgrade_authority_account: &AccountInfo,
219-
program_account: &AccountInfo,
220218
programdata_account: &AccountInfo,
221219
program_id: &Pubkey,
222220
) -> Result<(), ProgramError> {
223-
let program_deserialized: UpgradeableLoaderState =
224-
bincode::deserialize(&program_account.try_borrow_data()?)
225-
.map_err(|_| OracleError::DeserializationError)?;
226221
let programdata_deserialized: UpgradeableLoaderState =
227222
bincode::deserialize(&programdata_account.try_borrow_data()?)
228223
.map_err(|_| OracleError::DeserializationError)?;
229224

230-
// 1. program_account is actually this program's account
225+
// 1. programdata_account is actually this program's buffer
226+
let (programdata_address, _) =
227+
Pubkey::find_program_address(&[&program_id.to_bytes()], &bpf_loader_upgradeable::id());
228+
231229
pyth_assert(
232-
program_account.key.eq(program_id) && program_account.executable,
230+
programdata_address.eq(programdata_account.key),
233231
OracleError::InvalidUpgradeAuthority.into(),
234232
)?;
235233

236-
// 2. programdata_account is actually this program's buffer
237-
if let UpgradeableLoaderState::Program {
238-
programdata_address,
239-
} = program_deserialized
240-
{
241-
pyth_assert(
242-
programdata_address.eq(programdata_account.key),
243-
OracleError::InvalidUpgradeAuthority.into(),
244-
)?;
245-
} else {
246-
return Err(OracleError::InvalidUpgradeAuthority.into());
247-
}
248234

249-
// 3. upgrade_authority_account is actually the authority inside programdata_account
235+
// 2. upgrade_authority_account is actually the authority inside programdata_account
250236
if let UpgradeableLoaderState::ProgramData {
251237
slot: _,
252238
upgrade_authority_address: Some(upgrade_authority_key),

0 commit comments

Comments
 (0)