|
@@ -15,9 +15,9 @@ use std::ops::Deref;
|
|
|
|
|
|
/// Type validating that the account is the given Program
|
|
/// Type validating that the account is the given Program
|
|
///
|
|
///
|
|
-/// The type has a `programdata_address` property that will be set
|
|
|
|
|
|
+/// The type has a `programdata_address` function that will return `Option::Some`
|
|
/// if the program is owned by the [`BPFUpgradeableLoader`](https://docs.rs/solana-program/latest/solana_program/bpf_loader_upgradeable/index.html)
|
|
/// if the program is owned by the [`BPFUpgradeableLoader`](https://docs.rs/solana-program/latest/solana_program/bpf_loader_upgradeable/index.html)
|
|
-/// and will contain the `programdata_address` property of the `Program` variant of the [`UpgradeableLoaderState`](https://docs.rs/solana-program/latest/solana_program/bpf_loader_upgradeable/enum.UpgradeableLoaderState.html) enum.
|
|
|
|
|
|
+/// which will contain the `programdata_address` property of the `Program` variant of the [`UpgradeableLoaderState`](https://docs.rs/solana-program/latest/solana_program/bpf_loader_upgradeable/enum.UpgradeableLoaderState.html) enum.
|
|
///
|
|
///
|
|
/// # Table of Contents
|
|
/// # Table of Contents
|
|
/// - [Basic Functionality](#basic-functionality)
|
|
/// - [Basic Functionality](#basic-functionality)
|
|
@@ -47,7 +47,7 @@ use std::ops::Deref;
|
|
/// pub struct SetAdminSettings<'info> {
|
|
/// pub struct SetAdminSettings<'info> {
|
|
/// #[account(mut, seeds = [b"admin"], bump)]
|
|
/// #[account(mut, seeds = [b"admin"], bump)]
|
|
/// pub admin_settings: Account<'info, AdminSettings>,
|
|
/// pub admin_settings: Account<'info, AdminSettings>,
|
|
-/// #[account(constraint = program.programdata_address() == Some(program_data.key()))]
|
|
|
|
|
|
+/// #[account(constraint = program.programdata_address()? == Some(program_data.key()))]
|
|
/// pub program: Program<'info, MyProgram>,
|
|
/// pub program: Program<'info, MyProgram>,
|
|
/// #[account(constraint = program_data.upgrade_authority_address == Some(authority.key()))]
|
|
/// #[account(constraint = program_data.upgrade_authority_address == Some(authority.key()))]
|
|
/// pub program_data: Account<'info, ProgramData>,
|
|
/// pub program_data: Account<'info, ProgramData>,
|
|
@@ -60,7 +60,7 @@ use std::ops::Deref;
|
|
///
|
|
///
|
|
/// - `program` is the account of the program itself.
|
|
/// - `program` is the account of the program itself.
|
|
/// Its constraint checks that `program_data` is the account that contains the program's upgrade authority.
|
|
/// Its constraint checks that `program_data` is the account that contains the program's upgrade authority.
|
|
-/// Implicitly, this checks that `program` is a BPFUpgradeable program (`program.programdata_address()`
|
|
|
|
|
|
+/// Implicitly, this checks that `program` is a BPFUpgradeable program (`program.programdata_address()?`
|
|
/// will be `None` if it's not).
|
|
/// will be `None` if it's not).
|
|
/// - `program_data`'s constraint checks that its upgrade authority is the `authority` account.
|
|
/// - `program_data`'s constraint checks that its upgrade authority is the `authority` account.
|
|
/// - Finally, `authority` needs to sign the transaction.
|
|
/// - Finally, `authority` needs to sign the transaction.
|
|
@@ -77,24 +77,19 @@ use std::ops::Deref;
|
|
#[derive(Clone)]
|
|
#[derive(Clone)]
|
|
pub struct Program<'info, T: Id + Clone> {
|
|
pub struct Program<'info, T: Id + Clone> {
|
|
info: AccountInfo<'info>,
|
|
info: AccountInfo<'info>,
|
|
- programdata_address: Option<Pubkey>,
|
|
|
|
_phantom: PhantomData<T>,
|
|
_phantom: PhantomData<T>,
|
|
}
|
|
}
|
|
|
|
|
|
impl<'info, T: Id + Clone + fmt::Debug> fmt::Debug for Program<'info, T> {
|
|
impl<'info, T: Id + Clone + fmt::Debug> fmt::Debug for Program<'info, T> {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
- f.debug_struct("Program")
|
|
|
|
- .field("info", &self.info)
|
|
|
|
- .field("programdata_address", &self.programdata_address)
|
|
|
|
- .finish()
|
|
|
|
|
|
+ f.debug_struct("Program").field("info", &self.info).finish()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
impl<'a, T: Id + Clone> Program<'a, T> {
|
|
impl<'a, T: Id + Clone> Program<'a, T> {
|
|
- fn new(info: AccountInfo<'a>, programdata_address: Option<Pubkey>) -> Program<'a, T> {
|
|
|
|
|
|
+ fn new(info: AccountInfo<'a>) -> Program<'a, T> {
|
|
Self {
|
|
Self {
|
|
info,
|
|
info,
|
|
- programdata_address,
|
|
|
|
_phantom: PhantomData,
|
|
_phantom: PhantomData,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -108,8 +103,13 @@ impl<'a, T: Id + Clone> Program<'a, T> {
|
|
if !info.executable {
|
|
if !info.executable {
|
|
return Err(ErrorCode::InvalidProgramExecutable.into());
|
|
return Err(ErrorCode::InvalidProgramExecutable.into());
|
|
}
|
|
}
|
|
- let programdata_address = if *info.owner == bpf_loader_upgradeable::ID {
|
|
|
|
- let mut data: &[u8] = &info.try_borrow_data()?;
|
|
|
|
|
|
+
|
|
|
|
+ Ok(Program::new(info.clone()))
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ pub fn programdata_address(&self) -> Result<Option<Pubkey>> {
|
|
|
|
+ if *self.info.owner == bpf_loader_upgradeable::ID {
|
|
|
|
+ let mut data: &[u8] = &self.info.try_borrow_data()?;
|
|
let upgradable_loader_state =
|
|
let upgradable_loader_state =
|
|
UpgradeableLoaderState::try_deserialize_unchecked(&mut data)?;
|
|
UpgradeableLoaderState::try_deserialize_unchecked(&mut data)?;
|
|
|
|
|
|
@@ -122,24 +122,18 @@ impl<'a, T: Id + Clone> Program<'a, T> {
|
|
slot: _,
|
|
slot: _,
|
|
upgrade_authority_address: _,
|
|
upgrade_authority_address: _,
|
|
} => {
|
|
} => {
|
|
- // Unreachable because check above already
|
|
|
|
|
|
+ // Unreachable because check in try_from
|
|
// ensures that program is executable
|
|
// ensures that program is executable
|
|
// and therefore a program account.
|
|
// and therefore a program account.
|
|
unreachable!()
|
|
unreachable!()
|
|
}
|
|
}
|
|
UpgradeableLoaderState::Program {
|
|
UpgradeableLoaderState::Program {
|
|
programdata_address,
|
|
programdata_address,
|
|
- } => Some(programdata_address),
|
|
|
|
|
|
+ } => Ok(Some(programdata_address)),
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- None
|
|
|
|
- };
|
|
|
|
-
|
|
|
|
- Ok(Program::new(info.clone(), programdata_address))
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- pub fn programdata_address(&self) -> Option<Pubkey> {
|
|
|
|
- self.programdata_address
|
|
|
|
|
|
+ Ok(None)
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|