Restore ability for programs to upgrade themselves (#20265)
* Make helper associated fn * Add feature definition * Add handling to preserve program-id write lock when upgradeable loader is present; restore bpf upgrade-self test * Use single feature
This commit is contained in:
@ -354,6 +354,9 @@ impl Message {
|
||||
}
|
||||
|
||||
pub fn is_writable(&self, i: usize, demote_program_write_locks: bool) -> bool {
|
||||
let demote_program_id = demote_program_write_locks
|
||||
&& self.is_key_called_as_program(i)
|
||||
&& !self.is_upgradeable_loader_present();
|
||||
(i < (self.header.num_required_signatures - self.header.num_readonly_signed_accounts)
|
||||
as usize
|
||||
|| (i >= self.header.num_required_signatures as usize
|
||||
@ -363,7 +366,7 @@ impl Message {
|
||||
let key = self.account_keys[i];
|
||||
sysvar::is_sysvar_id(&key) || BUILTIN_PROGRAMS_KEYS.contains(&key)
|
||||
}
|
||||
&& !(demote_program_write_locks && self.is_key_called_as_program(i))
|
||||
&& !demote_program_id
|
||||
}
|
||||
|
||||
pub fn is_signer(&self, i: usize) -> bool {
|
||||
@ -503,6 +506,13 @@ impl Message {
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns true if any account is the bpf upgradeable loader
|
||||
pub fn is_upgradeable_loader_present(&self) -> bool {
|
||||
self.account_keys
|
||||
.iter()
|
||||
.any(|&key| key == bpf_loader_upgradeable::id())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -1,5 +1,6 @@
|
||||
use {
|
||||
crate::{
|
||||
bpf_loader_upgradeable,
|
||||
message::{legacy::BUILTIN_PROGRAMS_KEYS, v0},
|
||||
pubkey::Pubkey,
|
||||
sysvar,
|
||||
@ -99,8 +100,12 @@ impl MappedMessage {
|
||||
pub fn is_writable(&self, key_index: usize, demote_program_write_locks: bool) -> bool {
|
||||
if self.is_writable_index(key_index) {
|
||||
if let Some(key) = self.get_account_key(key_index) {
|
||||
return !(sysvar::is_sysvar_id(key) || BUILTIN_PROGRAMS_KEYS.contains(key)
|
||||
|| (demote_program_write_locks && self.is_key_called_as_program(key_index)));
|
||||
let demote_program_id = demote_program_write_locks
|
||||
&& self.is_key_called_as_program(key_index)
|
||||
&& !self.is_upgradeable_loader_present();
|
||||
return !(sysvar::is_sysvar_id(key)
|
||||
|| BUILTIN_PROGRAMS_KEYS.contains(key)
|
||||
|| demote_program_id);
|
||||
}
|
||||
}
|
||||
false
|
||||
@ -116,6 +121,12 @@ impl MappedMessage {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if any account is the bpf upgradeable loader
|
||||
pub fn is_upgradeable_loader_present(&self) -> bool {
|
||||
self.account_keys_iter()
|
||||
.any(|&key| key == bpf_loader_upgradeable::id())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -308,6 +308,14 @@ impl SanitizedMessage {
|
||||
.saturating_add(num_secp256k1_signatures),
|
||||
)
|
||||
}
|
||||
|
||||
/// Inspect all message keys for the bpf upgradeable loader
|
||||
pub fn is_upgradeable_loader_present(&self) -> bool {
|
||||
match self {
|
||||
Self::Legacy(message) => message.is_upgradeable_loader_present(),
|
||||
Self::V0(message) => message.is_upgradeable_loader_present(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
Reference in New Issue
Block a user