Revert deprecate executable feature (#309)
* revert deprecate executable feature * add native loader account transfer test --------- Co-authored-by: HaoranYi <haoran.yi@solana.com>
This commit is contained in:
parent
aba8ce5f3e
commit
0f8f8cd970
|
@ -44,7 +44,7 @@ use {
|
|||
},
|
||||
solana_rpc_client_nonce_utils::blockhash_query::BlockhashQuery,
|
||||
solana_sdk::{
|
||||
account::{is_executable, Account},
|
||||
account::Account,
|
||||
account_utils::StateMut,
|
||||
bpf_loader, bpf_loader_deprecated,
|
||||
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
|
||||
|
@ -1066,15 +1066,6 @@ fn get_default_program_keypair(program_location: &Option<String>) -> Keypair {
|
|||
program_keypair
|
||||
}
|
||||
|
||||
fn is_account_executable(account: &Account) -> bool {
|
||||
if account.owner == bpf_loader_deprecated::id() || account.owner == bpf_loader::id() {
|
||||
account.executable
|
||||
} else {
|
||||
let feature_set = FeatureSet::all_enabled();
|
||||
is_executable(account, &feature_set)
|
||||
}
|
||||
}
|
||||
|
||||
/// Deploy program using upgradeable loader. It also can process program upgrades
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn process_program_deploy(
|
||||
|
@ -1131,7 +1122,7 @@ fn process_program_deploy(
|
|||
.into());
|
||||
}
|
||||
|
||||
if !is_account_executable(&account) {
|
||||
if !account.executable {
|
||||
// Continue an initial deploy
|
||||
true
|
||||
} else if let Ok(UpgradeableLoaderState::Program {
|
||||
|
@ -2534,7 +2525,7 @@ fn complete_partial_program_init(
|
|||
) -> Result<(Vec<Instruction>, u64), Box<dyn std::error::Error>> {
|
||||
let mut instructions: Vec<Instruction> = vec![];
|
||||
let mut balance_needed = 0;
|
||||
if is_account_executable(account) {
|
||||
if account.executable {
|
||||
return Err("Buffer account is already executable".into());
|
||||
}
|
||||
if account.owner != *loader_id && !system_program::check_id(&account.owner) {
|
||||
|
|
|
@ -14,11 +14,9 @@ use {
|
|||
solana_rpc_client::rpc_client::RpcClient,
|
||||
solana_rpc_client_nonce_utils::blockhash_query::BlockhashQuery,
|
||||
solana_sdk::{
|
||||
account::is_executable,
|
||||
account_utils::StateMut,
|
||||
bpf_loader_upgradeable::{self, UpgradeableLoaderState},
|
||||
commitment_config::CommitmentConfig,
|
||||
feature_set::FeatureSet,
|
||||
pubkey::Pubkey,
|
||||
signature::{Keypair, NullSigner, Signer},
|
||||
},
|
||||
|
@ -102,7 +100,7 @@ fn test_cli_program_deploy_non_upgradeable() {
|
|||
let account0 = rpc_client.get_account(&program_id).unwrap();
|
||||
assert_eq!(account0.lamports, minimum_balance_for_program);
|
||||
assert_eq!(account0.owner, bpf_loader_upgradeable::id());
|
||||
assert!(is_executable(&account0, &FeatureSet::all_enabled()));
|
||||
assert!(account0.executable);
|
||||
|
||||
let (programdata_pubkey, _) =
|
||||
Pubkey::find_program_address(&[program_id.as_ref()], &bpf_loader_upgradeable::id());
|
||||
|
@ -112,10 +110,7 @@ fn test_cli_program_deploy_non_upgradeable() {
|
|||
minimum_balance_for_programdata
|
||||
);
|
||||
assert_eq!(programdata_account.owner, bpf_loader_upgradeable::id());
|
||||
assert!(!is_executable(
|
||||
&programdata_account,
|
||||
&FeatureSet::all_enabled()
|
||||
));
|
||||
assert!(!programdata_account.executable);
|
||||
assert_eq!(
|
||||
programdata_account.data[UpgradeableLoaderState::size_of_programdata_metadata()..],
|
||||
program_data[..]
|
||||
|
@ -143,7 +138,7 @@ fn test_cli_program_deploy_non_upgradeable() {
|
|||
.unwrap();
|
||||
assert_eq!(account1.lamports, minimum_balance_for_program);
|
||||
assert_eq!(account1.owner, bpf_loader_upgradeable::id());
|
||||
assert!(is_executable(&account1, &FeatureSet::all_enabled()));
|
||||
assert!(account1.executable);
|
||||
let (programdata_pubkey, _) = Pubkey::find_program_address(
|
||||
&[custom_address_keypair.pubkey().as_ref()],
|
||||
&bpf_loader_upgradeable::id(),
|
||||
|
@ -154,10 +149,7 @@ fn test_cli_program_deploy_non_upgradeable() {
|
|||
minimum_balance_for_programdata
|
||||
);
|
||||
assert_eq!(programdata_account.owner, bpf_loader_upgradeable::id());
|
||||
assert!(!is_executable(
|
||||
&programdata_account,
|
||||
&FeatureSet::all_enabled()
|
||||
));
|
||||
assert!(!programdata_account.executable);
|
||||
assert_eq!(
|
||||
programdata_account.data[UpgradeableLoaderState::size_of_programdata_metadata()..],
|
||||
program_data[..]
|
||||
|
@ -385,7 +377,7 @@ fn test_cli_program_deploy_with_authority() {
|
|||
let program_account = rpc_client.get_account(&program_keypair.pubkey()).unwrap();
|
||||
assert_eq!(program_account.lamports, minimum_balance_for_program);
|
||||
assert_eq!(program_account.owner, bpf_loader_upgradeable::id());
|
||||
assert!(is_executable(&program_account, &FeatureSet::all_enabled()));
|
||||
assert!(program_account.executable);
|
||||
let (programdata_pubkey, _) = Pubkey::find_program_address(
|
||||
&[program_keypair.pubkey().as_ref()],
|
||||
&bpf_loader_upgradeable::id(),
|
||||
|
@ -396,10 +388,7 @@ fn test_cli_program_deploy_with_authority() {
|
|||
minimum_balance_for_programdata
|
||||
);
|
||||
assert_eq!(programdata_account.owner, bpf_loader_upgradeable::id());
|
||||
assert!(!is_executable(
|
||||
&programdata_account,
|
||||
&FeatureSet::all_enabled()
|
||||
));
|
||||
assert!(!programdata_account.executable);
|
||||
assert_eq!(
|
||||
programdata_account.data[UpgradeableLoaderState::size_of_programdata_metadata()..],
|
||||
program_data[..]
|
||||
|
@ -433,7 +422,7 @@ fn test_cli_program_deploy_with_authority() {
|
|||
let program_account = rpc_client.get_account(&program_pubkey).unwrap();
|
||||
assert_eq!(program_account.lamports, minimum_balance_for_program);
|
||||
assert_eq!(program_account.owner, bpf_loader_upgradeable::id());
|
||||
assert!(is_executable(&program_account, &FeatureSet::all_enabled()));
|
||||
assert!(program_account.executable);
|
||||
let (programdata_pubkey, _) =
|
||||
Pubkey::find_program_address(&[program_pubkey.as_ref()], &bpf_loader_upgradeable::id());
|
||||
let programdata_account = rpc_client.get_account(&programdata_pubkey).unwrap();
|
||||
|
@ -442,10 +431,7 @@ fn test_cli_program_deploy_with_authority() {
|
|||
minimum_balance_for_programdata
|
||||
);
|
||||
assert_eq!(programdata_account.owner, bpf_loader_upgradeable::id());
|
||||
assert!(!is_executable(
|
||||
&programdata_account,
|
||||
&FeatureSet::all_enabled()
|
||||
));
|
||||
assert!(program_account.executable);
|
||||
assert_eq!(
|
||||
programdata_account.data[UpgradeableLoaderState::size_of_programdata_metadata()..],
|
||||
program_data[..]
|
||||
|
@ -470,7 +456,7 @@ fn test_cli_program_deploy_with_authority() {
|
|||
let program_account = rpc_client.get_account(&program_pubkey).unwrap();
|
||||
assert_eq!(program_account.lamports, minimum_balance_for_program);
|
||||
assert_eq!(program_account.owner, bpf_loader_upgradeable::id());
|
||||
assert!(is_executable(&program_account, &FeatureSet::all_enabled()));
|
||||
assert!(program_account.executable);
|
||||
let (programdata_pubkey, _) =
|
||||
Pubkey::find_program_address(&[program_pubkey.as_ref()], &bpf_loader_upgradeable::id());
|
||||
let programdata_account = rpc_client.get_account(&programdata_pubkey).unwrap();
|
||||
|
@ -479,10 +465,7 @@ fn test_cli_program_deploy_with_authority() {
|
|||
minimum_balance_for_programdata
|
||||
);
|
||||
assert_eq!(programdata_account.owner, bpf_loader_upgradeable::id());
|
||||
assert!(!is_executable(
|
||||
&programdata_account,
|
||||
&FeatureSet::all_enabled()
|
||||
));
|
||||
assert!(program_account.executable);
|
||||
assert_eq!(
|
||||
programdata_account.data[UpgradeableLoaderState::size_of_programdata_metadata()..],
|
||||
program_data[..]
|
||||
|
@ -548,7 +531,7 @@ fn test_cli_program_deploy_with_authority() {
|
|||
let program_account = rpc_client.get_account(&program_pubkey).unwrap();
|
||||
assert_eq!(program_account.lamports, minimum_balance_for_program);
|
||||
assert_eq!(program_account.owner, bpf_loader_upgradeable::id());
|
||||
assert!(is_executable(&program_account, &FeatureSet::all_enabled()));
|
||||
assert!(program_account.executable);
|
||||
let (programdata_pubkey, _) =
|
||||
Pubkey::find_program_address(&[program_pubkey.as_ref()], &bpf_loader_upgradeable::id());
|
||||
let programdata_account = rpc_client.get_account(&programdata_pubkey).unwrap();
|
||||
|
@ -557,10 +540,7 @@ fn test_cli_program_deploy_with_authority() {
|
|||
minimum_balance_for_programdata
|
||||
);
|
||||
assert_eq!(programdata_account.owner, bpf_loader_upgradeable::id());
|
||||
assert!(!is_executable(
|
||||
&programdata_account,
|
||||
&FeatureSet::all_enabled()
|
||||
));
|
||||
assert!(program_account.executable);
|
||||
assert_eq!(
|
||||
programdata_account.data[UpgradeableLoaderState::size_of_programdata_metadata()..],
|
||||
program_data[..]
|
||||
|
|
|
@ -540,7 +540,6 @@ pub fn program(ledger_path: &Path, matches: &ArgMatches<'_>) {
|
|||
.get_current_instruction_context()
|
||||
.unwrap(),
|
||||
true, // copy_account_data
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -403,7 +403,7 @@ impl<'a> InvokeContext<'a> {
|
|||
})?;
|
||||
let borrowed_program_account = instruction_context
|
||||
.try_borrow_instruction_account(self.transaction_context, program_account_index)?;
|
||||
if !borrowed_program_account.is_executable(&self.feature_set) {
|
||||
if !borrowed_program_account.is_executable() {
|
||||
ic_msg!(self, "Account {} is not executable", callee_program_id);
|
||||
return Err(InstructionError::AccountNotExecutable);
|
||||
}
|
||||
|
@ -802,17 +802,17 @@ mod tests {
|
|||
MockInstruction::NoopFail => return Err(InstructionError::GenericError),
|
||||
MockInstruction::ModifyOwned => instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 0)?
|
||||
.set_data_from_slice(&[1], &invoke_context.feature_set)?,
|
||||
.set_data_from_slice(&[1])?,
|
||||
MockInstruction::ModifyNotOwned => instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.set_data_from_slice(&[1], &invoke_context.feature_set)?,
|
||||
.set_data_from_slice(&[1])?,
|
||||
MockInstruction::ModifyReadonly => instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 2)?
|
||||
.set_data_from_slice(&[1], &invoke_context.feature_set)?,
|
||||
.set_data_from_slice(&[1])?,
|
||||
MockInstruction::UnbalancedPush => {
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 0)?
|
||||
.checked_add_lamports(1, &invoke_context.feature_set)?;
|
||||
.checked_add_lamports(1)?;
|
||||
let program_id = *transaction_context.get_key_of_account_at_index(3)?;
|
||||
let metas = vec![
|
||||
AccountMeta::new_readonly(
|
||||
|
@ -843,7 +843,7 @@ mod tests {
|
|||
}
|
||||
MockInstruction::UnbalancedPop => instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 0)?
|
||||
.checked_add_lamports(1, &invoke_context.feature_set)?,
|
||||
.checked_add_lamports(1)?,
|
||||
MockInstruction::ConsumeComputeUnits {
|
||||
compute_units_to_consume,
|
||||
desired_result,
|
||||
|
@ -855,7 +855,7 @@ mod tests {
|
|||
}
|
||||
MockInstruction::Resize { new_len } => instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 0)?
|
||||
.set_data(vec![0; new_len as usize], &invoke_context.feature_set)?,
|
||||
.set_data(vec![0; new_len as usize])?,
|
||||
}
|
||||
} else {
|
||||
return Err(InstructionError::InvalidInstructionData);
|
||||
|
|
|
@ -221,16 +221,16 @@ mod tests {
|
|||
MockSystemInstruction::TransferLamports { lamports } => {
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 0)?
|
||||
.checked_sub_lamports(lamports, &invoke_context.feature_set)?;
|
||||
.checked_sub_lamports(lamports)?;
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.checked_add_lamports(lamports, &invoke_context.feature_set)?;
|
||||
.checked_add_lamports(lamports)?;
|
||||
Ok(())
|
||||
}
|
||||
MockSystemInstruction::ChangeData { data } => {
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.set_data(vec![data], &invoke_context.feature_set)?;
|
||||
.set_data(vec![data])?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -444,14 +444,14 @@ mod tests {
|
|||
MockSystemInstruction::DoWork { lamports, data } => {
|
||||
let mut dup_account = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 2)?;
|
||||
dup_account.checked_sub_lamports(lamports, &invoke_context.feature_set)?;
|
||||
to_account.checked_add_lamports(lamports, &invoke_context.feature_set)?;
|
||||
dup_account.set_data(vec![data], &invoke_context.feature_set)?;
|
||||
dup_account.checked_sub_lamports(lamports)?;
|
||||
to_account.checked_add_lamports(lamports)?;
|
||||
dup_account.set_data(vec![data])?;
|
||||
drop(dup_account);
|
||||
let mut from_account = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 0)?;
|
||||
from_account.checked_sub_lamports(lamports, &invoke_context.feature_set)?;
|
||||
to_account.checked_add_lamports(lamports, &invoke_context.feature_set)?;
|
||||
from_account.checked_sub_lamports(lamports)?;
|
||||
to_account.checked_add_lamports(lamports)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,7 +133,6 @@ pub fn invoke_builtin_function(
|
|||
.transaction_context
|
||||
.get_current_instruction_context()?,
|
||||
true, // copy_account_data // There is no VM so direct mapping can not be implemented here
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
|
||||
// Deserialize data back into instruction params
|
||||
|
@ -164,25 +163,18 @@ pub fn invoke_builtin_function(
|
|||
if borrowed_account.is_writable() {
|
||||
if let Some(account_info) = account_info_map.get(borrowed_account.get_key()) {
|
||||
if borrowed_account.get_lamports() != account_info.lamports() {
|
||||
borrowed_account
|
||||
.set_lamports(account_info.lamports(), &invoke_context.feature_set)?;
|
||||
borrowed_account.set_lamports(account_info.lamports())?;
|
||||
}
|
||||
|
||||
if borrowed_account
|
||||
.can_data_be_resized(account_info.data_len())
|
||||
.is_ok()
|
||||
&& borrowed_account
|
||||
.can_data_be_changed(&invoke_context.feature_set)
|
||||
.is_ok()
|
||||
&& borrowed_account.can_data_be_changed().is_ok()
|
||||
{
|
||||
borrowed_account.set_data_from_slice(
|
||||
&account_info.data.borrow(),
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
borrowed_account.set_data_from_slice(&account_info.data.borrow())?;
|
||||
}
|
||||
if borrowed_account.get_owner() != account_info.owner {
|
||||
borrowed_account
|
||||
.set_owner(account_info.owner.as_ref(), &invoke_context.feature_set)?;
|
||||
borrowed_account.set_owner(account_info.owner.as_ref())?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -293,17 +285,17 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
|
|||
.unwrap();
|
||||
if borrowed_account.get_lamports() != account_info.lamports() {
|
||||
borrowed_account
|
||||
.set_lamports(account_info.lamports(), &invoke_context.feature_set)
|
||||
.set_lamports(account_info.lamports())
|
||||
.unwrap();
|
||||
}
|
||||
let account_info_data = account_info.try_borrow_data().unwrap();
|
||||
// The redundant check helps to avoid the expensive data comparison if we can
|
||||
match borrowed_account
|
||||
.can_data_be_resized(account_info_data.len())
|
||||
.and_then(|_| borrowed_account.can_data_be_changed(&invoke_context.feature_set))
|
||||
.and_then(|_| borrowed_account.can_data_be_changed())
|
||||
{
|
||||
Ok(()) => borrowed_account
|
||||
.set_data_from_slice(&account_info_data, &invoke_context.feature_set)
|
||||
.set_data_from_slice(&account_info_data)
|
||||
.unwrap(),
|
||||
Err(err) if borrowed_account.get_data() != *account_info_data => {
|
||||
panic!("{err:?}");
|
||||
|
@ -313,7 +305,7 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
|
|||
// Change the owner at the end so that we are allowed to change the lamports and data before
|
||||
if borrowed_account.get_owner() != account_info.owner {
|
||||
borrowed_account
|
||||
.set_owner(account_info.owner.as_ref(), &invoke_context.feature_set)
|
||||
.set_owner(account_info.owner.as_ref())
|
||||
.unwrap();
|
||||
}
|
||||
if instruction_account.is_writable {
|
||||
|
|
|
@ -162,10 +162,9 @@ impl Processor {
|
|||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||
let mut lookup_table_account =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||
lookup_table_account.set_state(
|
||||
&ProgramState::LookupTable(LookupTableMeta::new(authority_key)),
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
lookup_table_account.set_state(&ProgramState::LookupTable(LookupTableMeta::new(
|
||||
authority_key,
|
||||
)))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -214,7 +213,7 @@ impl Processor {
|
|||
let mut lookup_table_meta = lookup_table.meta;
|
||||
lookup_table_meta.authority = None;
|
||||
AddressLookupTable::overwrite_meta_data(
|
||||
lookup_table_account.get_data_mut(&invoke_context.feature_set)?,
|
||||
lookup_table_account.get_data_mut()?,
|
||||
lookup_table_meta,
|
||||
)?;
|
||||
|
||||
|
@ -306,12 +305,11 @@ impl Processor {
|
|||
)?;
|
||||
{
|
||||
AddressLookupTable::overwrite_meta_data(
|
||||
lookup_table_account.get_data_mut(&invoke_context.feature_set)?,
|
||||
lookup_table_account.get_data_mut()?,
|
||||
lookup_table_meta,
|
||||
)?;
|
||||
for new_address in new_addresses {
|
||||
lookup_table_account
|
||||
.extend_from_slice(new_address.as_ref(), &invoke_context.feature_set)?;
|
||||
lookup_table_account.extend_from_slice(new_address.as_ref())?;
|
||||
}
|
||||
}
|
||||
drop(lookup_table_account);
|
||||
|
@ -383,7 +381,7 @@ impl Processor {
|
|||
lookup_table_meta.deactivation_slot = clock.slot;
|
||||
|
||||
AddressLookupTable::overwrite_meta_data(
|
||||
lookup_table_account.get_data_mut(&invoke_context.feature_set)?,
|
||||
lookup_table_account.get_data_mut()?,
|
||||
lookup_table_meta,
|
||||
)?;
|
||||
|
||||
|
@ -458,13 +456,13 @@ impl Processor {
|
|||
|
||||
let mut recipient_account =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, 2)?;
|
||||
recipient_account.checked_add_lamports(withdrawn_lamports, &invoke_context.feature_set)?;
|
||||
recipient_account.checked_add_lamports(withdrawn_lamports)?;
|
||||
drop(recipient_account);
|
||||
|
||||
let mut lookup_table_account =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||
lookup_table_account.set_data_length(0, &invoke_context.feature_set)?;
|
||||
lookup_table_account.set_lamports(0, &invoke_context.feature_set)?;
|
||||
lookup_table_account.set_data_length(0)?;
|
||||
lookup_table_account.set_lamports(0)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@ use {
|
|||
solana_sdk::{
|
||||
account::{Account, AccountSharedData},
|
||||
bpf_loader, bpf_loader_deprecated,
|
||||
feature_set::FeatureSet,
|
||||
pubkey::Pubkey,
|
||||
sysvar::rent::Rent,
|
||||
transaction_context::{IndexOfAccount, InstructionAccount, TransactionContext},
|
||||
|
@ -127,13 +126,7 @@ fn bench_serialize_unaligned(bencher: &mut Bencher) {
|
|||
.get_current_instruction_context()
|
||||
.unwrap();
|
||||
bencher.iter(|| {
|
||||
let _ = serialize_parameters(
|
||||
&transaction_context,
|
||||
instruction_context,
|
||||
false,
|
||||
&FeatureSet::all_enabled(),
|
||||
)
|
||||
.unwrap();
|
||||
let _ = serialize_parameters(&transaction_context, instruction_context, false).unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -144,13 +137,7 @@ fn bench_serialize_unaligned_copy_account_data(bencher: &mut Bencher) {
|
|||
.get_current_instruction_context()
|
||||
.unwrap();
|
||||
bencher.iter(|| {
|
||||
let _ = serialize_parameters(
|
||||
&transaction_context,
|
||||
instruction_context,
|
||||
true,
|
||||
&FeatureSet::all_enabled(),
|
||||
)
|
||||
.unwrap();
|
||||
let _ = serialize_parameters(&transaction_context, instruction_context, true).unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -162,13 +149,7 @@ fn bench_serialize_aligned(bencher: &mut Bencher) {
|
|||
.unwrap();
|
||||
|
||||
bencher.iter(|| {
|
||||
let _ = serialize_parameters(
|
||||
&transaction_context,
|
||||
instruction_context,
|
||||
false,
|
||||
&FeatureSet::all_enabled(),
|
||||
)
|
||||
.unwrap();
|
||||
let _ = serialize_parameters(&transaction_context, instruction_context, false).unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -180,13 +161,7 @@ fn bench_serialize_aligned_copy_account_data(bencher: &mut Bencher) {
|
|||
.unwrap();
|
||||
|
||||
bencher.iter(|| {
|
||||
let _ = serialize_parameters(
|
||||
&transaction_context,
|
||||
instruction_context,
|
||||
true,
|
||||
&FeatureSet::all_enabled(),
|
||||
)
|
||||
.unwrap();
|
||||
let _ = serialize_parameters(&transaction_context, instruction_context, true).unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -197,13 +172,7 @@ fn bench_serialize_unaligned_max_accounts(bencher: &mut Bencher) {
|
|||
.get_current_instruction_context()
|
||||
.unwrap();
|
||||
bencher.iter(|| {
|
||||
let _ = serialize_parameters(
|
||||
&transaction_context,
|
||||
instruction_context,
|
||||
false,
|
||||
&FeatureSet::all_enabled(),
|
||||
)
|
||||
.unwrap();
|
||||
let _ = serialize_parameters(&transaction_context, instruction_context, false).unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -215,12 +184,6 @@ fn bench_serialize_aligned_max_accounts(bencher: &mut Bencher) {
|
|||
.unwrap();
|
||||
|
||||
bencher.iter(|| {
|
||||
let _ = serialize_parameters(
|
||||
&transaction_context,
|
||||
instruction_context,
|
||||
false,
|
||||
&FeatureSet::all_enabled(),
|
||||
)
|
||||
.unwrap();
|
||||
let _ = serialize_parameters(&transaction_context, instruction_context, false).unwrap();
|
||||
});
|
||||
}
|
||||
|
|
|
@ -34,8 +34,7 @@ use {
|
|||
clock::Slot,
|
||||
entrypoint::{MAX_PERMITTED_DATA_INCREASE, SUCCESS},
|
||||
feature_set::{
|
||||
bpf_account_data_direct_mapping, deprecate_executable_meta_update_in_bpf_loader,
|
||||
enable_bpf_loader_set_authority_checked_ix, FeatureSet,
|
||||
bpf_account_data_direct_mapping, enable_bpf_loader_set_authority_checked_ix,
|
||||
},
|
||||
instruction::{AccountMeta, InstructionError},
|
||||
loader_upgradeable_instruction::UpgradeableLoaderInstruction,
|
||||
|
@ -172,7 +171,7 @@ fn write_program_data(
|
|||
let transaction_context = &invoke_context.transaction_context;
|
||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||
let mut program = instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||
let data = program.get_data_mut(&invoke_context.feature_set)?;
|
||||
let data = program.get_data_mut()?;
|
||||
let write_offset = program_data_offset.saturating_add(bytes.len());
|
||||
if data.len() < write_offset {
|
||||
ic_msg!(
|
||||
|
@ -402,7 +401,7 @@ pub fn process_instruction_inner(
|
|||
}
|
||||
|
||||
// Program Invocation
|
||||
if !program_account.is_executable(&invoke_context.feature_set) {
|
||||
if !program_account.is_executable() {
|
||||
ic_logger_msg!(log_collector, "Program is not executable");
|
||||
return Err(Box::new(InstructionError::IncorrectProgramId));
|
||||
}
|
||||
|
@ -460,12 +459,9 @@ fn process_loader_upgradeable_instruction(
|
|||
instruction_context.get_index_of_instruction_account_in_transaction(1)?,
|
||||
)?);
|
||||
|
||||
buffer.set_state(
|
||||
&UpgradeableLoaderState::Buffer {
|
||||
authority_address: authority_key,
|
||||
},
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
buffer.set_state(&UpgradeableLoaderState::Buffer {
|
||||
authority_address: authority_key,
|
||||
})?;
|
||||
}
|
||||
UpgradeableLoaderInstruction::Write { offset, bytes } => {
|
||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||
|
@ -589,8 +585,8 @@ fn process_loader_upgradeable_instruction(
|
|||
instruction_context.try_borrow_instruction_account(transaction_context, 3)?;
|
||||
let mut payer =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||
payer.checked_add_lamports(buffer.get_lamports(), &invoke_context.feature_set)?;
|
||||
buffer.set_lamports(0, &invoke_context.feature_set)?;
|
||||
payer.checked_add_lamports(buffer.get_lamports())?;
|
||||
buffer.set_lamports(0)?;
|
||||
}
|
||||
|
||||
let owner_id = *program_id;
|
||||
|
@ -644,15 +640,12 @@ fn process_loader_upgradeable_instruction(
|
|||
{
|
||||
let mut programdata =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, 1)?;
|
||||
programdata.set_state(
|
||||
&UpgradeableLoaderState::ProgramData {
|
||||
slot: clock.slot,
|
||||
upgrade_authority_address: authority_key,
|
||||
},
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
programdata.set_state(&UpgradeableLoaderState::ProgramData {
|
||||
slot: clock.slot,
|
||||
upgrade_authority_address: authority_key,
|
||||
})?;
|
||||
let dst_slice = programdata
|
||||
.get_data_mut(&invoke_context.feature_set)?
|
||||
.get_data_mut()?
|
||||
.get_mut(
|
||||
programdata_data_offset
|
||||
..programdata_data_offset.saturating_add(buffer_data_len),
|
||||
|
@ -665,30 +658,16 @@ fn process_loader_upgradeable_instruction(
|
|||
.get(buffer_data_offset..)
|
||||
.ok_or(InstructionError::AccountDataTooSmall)?;
|
||||
dst_slice.copy_from_slice(src_slice);
|
||||
buffer.set_data_length(
|
||||
UpgradeableLoaderState::size_of_buffer(0),
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
buffer.set_data_length(UpgradeableLoaderState::size_of_buffer(0))?;
|
||||
}
|
||||
|
||||
// Update the Program account
|
||||
let mut program =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, 2)?;
|
||||
program.set_state(
|
||||
&UpgradeableLoaderState::Program {
|
||||
programdata_address: programdata_key,
|
||||
},
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
|
||||
// Skip writing true to executable meta after bpf program deployment when
|
||||
// `deprecate_executable_meta_update_in_bpf_loader` feature is activated.
|
||||
if !invoke_context
|
||||
.feature_set
|
||||
.is_active(&deprecate_executable_meta_update_in_bpf_loader::id())
|
||||
{
|
||||
program.set_executable(true)?;
|
||||
}
|
||||
program.set_state(&UpgradeableLoaderState::Program {
|
||||
programdata_address: programdata_key,
|
||||
})?;
|
||||
program.set_executable(true)?;
|
||||
drop(program);
|
||||
|
||||
ic_logger_msg!(log_collector, "Deployed program {:?}", new_program_id);
|
||||
|
@ -710,7 +689,7 @@ fn process_loader_upgradeable_instruction(
|
|||
|
||||
let program =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, 1)?;
|
||||
if !program.is_executable(&invoke_context.feature_set) {
|
||||
if !program.is_executable() {
|
||||
ic_logger_msg!(log_collector, "Program account not executable");
|
||||
return Err(InstructionError::AccountNotExecutable);
|
||||
}
|
||||
|
@ -841,15 +820,12 @@ fn process_loader_upgradeable_instruction(
|
|||
let mut programdata =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||
{
|
||||
programdata.set_state(
|
||||
&UpgradeableLoaderState::ProgramData {
|
||||
slot: clock.slot,
|
||||
upgrade_authority_address: authority_key,
|
||||
},
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
programdata.set_state(&UpgradeableLoaderState::ProgramData {
|
||||
slot: clock.slot,
|
||||
upgrade_authority_address: authority_key,
|
||||
})?;
|
||||
let dst_slice = programdata
|
||||
.get_data_mut(&invoke_context.feature_set)?
|
||||
.get_data_mut()?
|
||||
.get_mut(
|
||||
programdata_data_offset
|
||||
..programdata_data_offset.saturating_add(buffer_data_len),
|
||||
|
@ -864,7 +840,7 @@ fn process_loader_upgradeable_instruction(
|
|||
dst_slice.copy_from_slice(src_slice);
|
||||
}
|
||||
programdata
|
||||
.get_data_mut(&invoke_context.feature_set)?
|
||||
.get_data_mut()?
|
||||
.get_mut(programdata_data_offset.saturating_add(buffer_data_len)..)
|
||||
.ok_or(InstructionError::AccountDataTooSmall)?
|
||||
.fill(0);
|
||||
|
@ -879,14 +855,10 @@ fn process_loader_upgradeable_instruction(
|
|||
.get_lamports()
|
||||
.saturating_add(buffer_lamports)
|
||||
.saturating_sub(programdata_balance_required),
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
buffer.set_lamports(0, &invoke_context.feature_set)?;
|
||||
programdata.set_lamports(programdata_balance_required, &invoke_context.feature_set)?;
|
||||
buffer.set_data_length(
|
||||
UpgradeableLoaderState::size_of_buffer(0),
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
buffer.set_lamports(0)?;
|
||||
programdata.set_lamports(programdata_balance_required)?;
|
||||
buffer.set_data_length(UpgradeableLoaderState::size_of_buffer(0))?;
|
||||
|
||||
ic_logger_msg!(log_collector, "Upgraded program {:?}", new_program_id);
|
||||
}
|
||||
|
@ -922,12 +894,9 @@ fn process_loader_upgradeable_instruction(
|
|||
ic_logger_msg!(log_collector, "Buffer authority did not sign");
|
||||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
account.set_state(
|
||||
&UpgradeableLoaderState::Buffer {
|
||||
authority_address: new_authority.cloned(),
|
||||
},
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
account.set_state(&UpgradeableLoaderState::Buffer {
|
||||
authority_address: new_authority.cloned(),
|
||||
})?;
|
||||
}
|
||||
UpgradeableLoaderState::ProgramData {
|
||||
slot,
|
||||
|
@ -945,13 +914,10 @@ fn process_loader_upgradeable_instruction(
|
|||
ic_logger_msg!(log_collector, "Upgrade authority did not sign");
|
||||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
account.set_state(
|
||||
&UpgradeableLoaderState::ProgramData {
|
||||
slot,
|
||||
upgrade_authority_address: new_authority.cloned(),
|
||||
},
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
account.set_state(&UpgradeableLoaderState::ProgramData {
|
||||
slot,
|
||||
upgrade_authority_address: new_authority.cloned(),
|
||||
})?;
|
||||
}
|
||||
_ => {
|
||||
ic_logger_msg!(log_collector, "Account does not support authorities");
|
||||
|
@ -997,12 +963,9 @@ fn process_loader_upgradeable_instruction(
|
|||
ic_logger_msg!(log_collector, "New authority did not sign");
|
||||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
account.set_state(
|
||||
&UpgradeableLoaderState::Buffer {
|
||||
authority_address: Some(*new_authority_key),
|
||||
},
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
account.set_state(&UpgradeableLoaderState::Buffer {
|
||||
authority_address: Some(*new_authority_key),
|
||||
})?;
|
||||
}
|
||||
UpgradeableLoaderState::ProgramData {
|
||||
slot,
|
||||
|
@ -1024,13 +987,10 @@ fn process_loader_upgradeable_instruction(
|
|||
ic_logger_msg!(log_collector, "New authority did not sign");
|
||||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
account.set_state(
|
||||
&UpgradeableLoaderState::ProgramData {
|
||||
slot,
|
||||
upgrade_authority_address: Some(*new_authority_key),
|
||||
},
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
account.set_state(&UpgradeableLoaderState::ProgramData {
|
||||
slot,
|
||||
upgrade_authority_address: Some(*new_authority_key),
|
||||
})?;
|
||||
}
|
||||
_ => {
|
||||
ic_logger_msg!(log_collector, "Account does not support authorities");
|
||||
|
@ -1055,19 +1015,13 @@ fn process_loader_upgradeable_instruction(
|
|||
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||
let close_key = *close_account.get_key();
|
||||
let close_account_state = close_account.get_state()?;
|
||||
close_account.set_data_length(
|
||||
UpgradeableLoaderState::size_of_uninitialized(),
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
close_account.set_data_length(UpgradeableLoaderState::size_of_uninitialized())?;
|
||||
match close_account_state {
|
||||
UpgradeableLoaderState::Uninitialized => {
|
||||
let mut recipient_account = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?;
|
||||
recipient_account.checked_add_lamports(
|
||||
close_account.get_lamports(),
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
close_account.set_lamports(0, &invoke_context.feature_set)?;
|
||||
recipient_account.checked_add_lamports(close_account.get_lamports())?;
|
||||
close_account.set_lamports(0)?;
|
||||
|
||||
ic_logger_msg!(log_collector, "Closed Uninitialized {}", close_key);
|
||||
}
|
||||
|
@ -1079,7 +1033,6 @@ fn process_loader_upgradeable_instruction(
|
|||
transaction_context,
|
||||
instruction_context,
|
||||
&log_collector,
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
|
||||
ic_logger_msg!(log_collector, "Closed Buffer {}", close_key);
|
||||
|
@ -1126,7 +1079,6 @@ fn process_loader_upgradeable_instruction(
|
|||
transaction_context,
|
||||
instruction_context,
|
||||
&log_collector,
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
let clock = invoke_context.get_sysvar_cache().get_clock()?;
|
||||
invoke_context.programs_modified_by_tx.replenish(
|
||||
|
@ -1277,7 +1229,7 @@ fn process_loader_upgradeable_instruction(
|
|||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||
let mut programdata_account = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, PROGRAM_DATA_ACCOUNT_INDEX)?;
|
||||
programdata_account.set_data_length(new_len, &invoke_context.feature_set)?;
|
||||
programdata_account.set_data_length(new_len)?;
|
||||
|
||||
let programdata_data_offset = UpgradeableLoaderState::size_of_programdata_metadata();
|
||||
|
||||
|
@ -1298,13 +1250,10 @@ fn process_loader_upgradeable_instruction(
|
|||
|
||||
let mut programdata_account = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, PROGRAM_DATA_ACCOUNT_INDEX)?;
|
||||
programdata_account.set_state(
|
||||
&UpgradeableLoaderState::ProgramData {
|
||||
slot: clock_slot,
|
||||
upgrade_authority_address,
|
||||
},
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
programdata_account.set_state(&UpgradeableLoaderState::ProgramData {
|
||||
slot: clock_slot,
|
||||
upgrade_authority_address,
|
||||
})?;
|
||||
|
||||
ic_logger_msg!(
|
||||
log_collector,
|
||||
|
@ -1322,7 +1271,6 @@ fn common_close_account(
|
|||
transaction_context: &TransactionContext,
|
||||
instruction_context: &InstructionContext,
|
||||
log_collector: &Option<Rc<RefCell<LogCollector>>>,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
if authority_address.is_none() {
|
||||
ic_logger_msg!(log_collector, "Account is immutable");
|
||||
|
@ -1346,9 +1294,9 @@ fn common_close_account(
|
|||
let mut recipient_account =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, 1)?;
|
||||
|
||||
recipient_account.checked_add_lamports(close_account.get_lamports(), feature_set)?;
|
||||
close_account.set_lamports(0, feature_set)?;
|
||||
close_account.set_state(&UpgradeableLoaderState::Uninitialized, feature_set)?;
|
||||
recipient_account.checked_add_lamports(close_account.get_lamports())?;
|
||||
close_account.set_lamports(0)?;
|
||||
close_account.set_state(&UpgradeableLoaderState::Uninitialized)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1383,7 +1331,6 @@ fn execute<'a, 'b: 'a>(
|
|||
invoke_context.transaction_context,
|
||||
instruction_context,
|
||||
!direct_mapping,
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
serialize_time.stop();
|
||||
|
||||
|
@ -1464,15 +1411,13 @@ fn execute<'a, 'b: 'a>(
|
|||
instruction_account_index as IndexOfAccount,
|
||||
)?;
|
||||
|
||||
error = EbpfError::SyscallError(Box::new(
|
||||
if account.is_executable(&invoke_context.feature_set) {
|
||||
InstructionError::ExecutableDataModified
|
||||
} else if account.is_writable() {
|
||||
InstructionError::ExternalAccountDataModified
|
||||
} else {
|
||||
InstructionError::ReadonlyDataModified
|
||||
},
|
||||
));
|
||||
error = EbpfError::SyscallError(Box::new(if account.is_executable() {
|
||||
InstructionError::ExecutableDataModified
|
||||
} else if account.is_writable() {
|
||||
InstructionError::ExternalAccountDataModified
|
||||
} else {
|
||||
InstructionError::ReadonlyDataModified
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1500,7 +1445,6 @@ fn execute<'a, 'b: 'a>(
|
|||
copy_account_data,
|
||||
parameter_bytes,
|
||||
&invoke_context.get_syscall_context()?.accounts_metadata,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -1630,9 +1574,6 @@ mod tests {
|
|||
expected_result,
|
||||
Entrypoint::vm,
|
||||
|invoke_context| {
|
||||
let mut features = FeatureSet::all_enabled();
|
||||
features.deactivate(&deprecate_executable_meta_update_in_bpf_loader::id());
|
||||
invoke_context.feature_set = Arc::new(features);
|
||||
test_utils::load_all_invoked_programs(invoke_context);
|
||||
},
|
||||
|_invoke_context| {},
|
||||
|
@ -1721,9 +1662,6 @@ mod tests {
|
|||
Err(InstructionError::ProgramFailedToComplete),
|
||||
Entrypoint::vm,
|
||||
|invoke_context| {
|
||||
let mut features = FeatureSet::all_enabled();
|
||||
features.deactivate(&deprecate_executable_meta_update_in_bpf_loader::id());
|
||||
invoke_context.feature_set = Arc::new(features);
|
||||
invoke_context.mock_set_remaining(0);
|
||||
test_utils::load_all_invoked_programs(invoke_context);
|
||||
},
|
||||
|
@ -2269,11 +2207,7 @@ mod tests {
|
|||
instruction_accounts,
|
||||
expected_result,
|
||||
Entrypoint::vm,
|
||||
|invoke_context| {
|
||||
let mut features = FeatureSet::all_enabled();
|
||||
features.deactivate(&deprecate_executable_meta_update_in_bpf_loader::id());
|
||||
invoke_context.feature_set = Arc::new(features);
|
||||
},
|
||||
|_invoke_context| {},
|
||||
|_invoke_context| {},
|
||||
)
|
||||
}
|
||||
|
|
|
@ -11,7 +11,6 @@ use {
|
|||
solana_sdk::{
|
||||
bpf_loader_deprecated,
|
||||
entrypoint::{BPF_ALIGN_OF_U128, MAX_PERMITTED_DATA_INCREASE, NON_DUP_MARKER},
|
||||
feature_set::FeatureSet,
|
||||
instruction::InstructionError,
|
||||
pubkey::Pubkey,
|
||||
system_instruction::MAX_PERMITTED_DATA_LENGTH,
|
||||
|
@ -94,7 +93,6 @@ impl Serializer {
|
|||
fn write_account(
|
||||
&mut self,
|
||||
account: &mut BorrowedAccount<'_>,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<u64, InstructionError> {
|
||||
let vm_data_addr = if self.copy_account_data {
|
||||
let vm_data_addr = self.vaddr.saturating_add(self.buffer.len() as u64);
|
||||
|
@ -103,7 +101,7 @@ impl Serializer {
|
|||
} else {
|
||||
self.push_region(true);
|
||||
let vaddr = self.vaddr;
|
||||
self.push_account_data_region(account, feature_set)?;
|
||||
self.push_account_data_region(account)?;
|
||||
vaddr
|
||||
};
|
||||
|
||||
|
@ -123,7 +121,7 @@ impl Serializer {
|
|||
.map_err(|_| InstructionError::InvalidArgument)?;
|
||||
self.region_start += BPF_ALIGN_OF_U128.saturating_sub(align_offset);
|
||||
// put the realloc padding in its own region
|
||||
self.push_region(account.can_data_be_changed(feature_set).is_ok());
|
||||
self.push_region(account.can_data_be_changed().is_ok());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -133,13 +131,12 @@ impl Serializer {
|
|||
fn push_account_data_region(
|
||||
&mut self,
|
||||
account: &mut BorrowedAccount<'_>,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
if !account.get_data().is_empty() {
|
||||
let region = match account_data_region_memory_state(account, feature_set) {
|
||||
let region = match account_data_region_memory_state(account) {
|
||||
MemoryState::Readable => MemoryRegion::new_readonly(account.get_data(), self.vaddr),
|
||||
MemoryState::Writable => {
|
||||
MemoryRegion::new_writable(account.get_data_mut(feature_set)?, self.vaddr)
|
||||
MemoryRegion::new_writable(account.get_data_mut()?, self.vaddr)
|
||||
}
|
||||
MemoryState::Cow(index_in_transaction) => {
|
||||
MemoryRegion::new_cow(account.get_data(), self.vaddr, index_in_transaction)
|
||||
|
@ -194,7 +191,6 @@ pub fn serialize_parameters(
|
|||
transaction_context: &TransactionContext,
|
||||
instruction_context: &InstructionContext,
|
||||
copy_account_data: bool,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<
|
||||
(
|
||||
AlignedMemory<HOST_ALIGN>,
|
||||
|
@ -243,7 +239,6 @@ pub fn serialize_parameters(
|
|||
instruction_context.get_instruction_data(),
|
||||
&program_id,
|
||||
copy_account_data,
|
||||
feature_set,
|
||||
)
|
||||
} else {
|
||||
serialize_parameters_aligned(
|
||||
|
@ -251,7 +246,6 @@ pub fn serialize_parameters(
|
|||
instruction_context.get_instruction_data(),
|
||||
&program_id,
|
||||
copy_account_data,
|
||||
feature_set,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -262,7 +256,6 @@ pub fn deserialize_parameters(
|
|||
copy_account_data: bool,
|
||||
buffer: &[u8],
|
||||
accounts_metadata: &[SerializedAccountMetadata],
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
let is_loader_deprecated = *instruction_context
|
||||
.try_borrow_last_program_account(transaction_context)?
|
||||
|
@ -276,7 +269,6 @@ pub fn deserialize_parameters(
|
|||
copy_account_data,
|
||||
buffer,
|
||||
account_lengths,
|
||||
feature_set,
|
||||
)
|
||||
} else {
|
||||
deserialize_parameters_aligned(
|
||||
|
@ -285,7 +277,6 @@ pub fn deserialize_parameters(
|
|||
copy_account_data,
|
||||
buffer,
|
||||
account_lengths,
|
||||
feature_set,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -295,7 +286,6 @@ fn serialize_parameters_unaligned(
|
|||
instruction_data: &[u8],
|
||||
program_id: &Pubkey,
|
||||
copy_account_data: bool,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<
|
||||
(
|
||||
AlignedMemory<HOST_ALIGN>,
|
||||
|
@ -346,9 +336,9 @@ fn serialize_parameters_unaligned(
|
|||
let vm_key_addr = s.write_all(account.get_key().as_ref());
|
||||
let vm_lamports_addr = s.write::<u64>(account.get_lamports().to_le());
|
||||
s.write::<u64>((account.get_data().len() as u64).to_le());
|
||||
let vm_data_addr = s.write_account(&mut account, feature_set)?;
|
||||
let vm_data_addr = s.write_account(&mut account)?;
|
||||
let vm_owner_addr = s.write_all(account.get_owner().as_ref());
|
||||
s.write::<u8>(account.is_executable(feature_set) as u8);
|
||||
s.write::<u8>(account.is_executable() as u8);
|
||||
s.write::<u64>((account.get_rent_epoch()).to_le());
|
||||
accounts_metadata.push(SerializedAccountMetadata {
|
||||
original_data_len: account.get_data().len(),
|
||||
|
@ -374,7 +364,6 @@ pub fn deserialize_parameters_unaligned<I: IntoIterator<Item = usize>>(
|
|||
copy_account_data: bool,
|
||||
buffer: &[u8],
|
||||
account_lengths: I,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut start = size_of::<u64>(); // number of accounts
|
||||
for (instruction_account_index, pre_len) in (0..instruction_context
|
||||
|
@ -396,7 +385,7 @@ pub fn deserialize_parameters_unaligned<I: IntoIterator<Item = usize>>(
|
|||
.ok_or(InstructionError::InvalidArgument)?,
|
||||
);
|
||||
if borrowed_account.get_lamports() != lamports {
|
||||
borrowed_account.set_lamports(lamports, feature_set)?;
|
||||
borrowed_account.set_lamports(lamports)?;
|
||||
}
|
||||
start += size_of::<u64>() // lamports
|
||||
+ size_of::<u64>(); // data length
|
||||
|
@ -407,9 +396,9 @@ pub fn deserialize_parameters_unaligned<I: IntoIterator<Item = usize>>(
|
|||
// The redundant check helps to avoid the expensive data comparison if we can
|
||||
match borrowed_account
|
||||
.can_data_be_resized(data.len())
|
||||
.and_then(|_| borrowed_account.can_data_be_changed(feature_set))
|
||||
.and_then(|_| borrowed_account.can_data_be_changed())
|
||||
{
|
||||
Ok(()) => borrowed_account.set_data_from_slice(data, feature_set)?,
|
||||
Ok(()) => borrowed_account.set_data_from_slice(data)?,
|
||||
Err(err) if borrowed_account.get_data() != data => return Err(err),
|
||||
_ => {}
|
||||
}
|
||||
|
@ -428,7 +417,6 @@ fn serialize_parameters_aligned(
|
|||
instruction_data: &[u8],
|
||||
program_id: &Pubkey,
|
||||
copy_account_data: bool,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<
|
||||
(
|
||||
AlignedMemory<HOST_ALIGN>,
|
||||
|
@ -478,13 +466,13 @@ fn serialize_parameters_aligned(
|
|||
s.write::<u8>(NON_DUP_MARKER);
|
||||
s.write::<u8>(borrowed_account.is_signer() as u8);
|
||||
s.write::<u8>(borrowed_account.is_writable() as u8);
|
||||
s.write::<u8>(borrowed_account.is_executable(feature_set) as u8);
|
||||
s.write::<u8>(borrowed_account.is_executable() as u8);
|
||||
s.write_all(&[0u8, 0, 0, 0]);
|
||||
let vm_key_addr = s.write_all(borrowed_account.get_key().as_ref());
|
||||
let vm_owner_addr = s.write_all(borrowed_account.get_owner().as_ref());
|
||||
let vm_lamports_addr = s.write::<u64>(borrowed_account.get_lamports().to_le());
|
||||
s.write::<u64>((borrowed_account.get_data().len() as u64).to_le());
|
||||
let vm_data_addr = s.write_account(&mut borrowed_account, feature_set)?;
|
||||
let vm_data_addr = s.write_account(&mut borrowed_account)?;
|
||||
s.write::<u64>((borrowed_account.get_rent_epoch()).to_le());
|
||||
accounts_metadata.push(SerializedAccountMetadata {
|
||||
original_data_len: borrowed_account.get_data().len(),
|
||||
|
@ -515,7 +503,6 @@ pub fn deserialize_parameters_aligned<I: IntoIterator<Item = usize>>(
|
|||
copy_account_data: bool,
|
||||
buffer: &[u8],
|
||||
account_lengths: I,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut start = size_of::<u64>(); // number of accounts
|
||||
for (instruction_account_index, pre_len) in (0..instruction_context
|
||||
|
@ -545,7 +532,7 @@ pub fn deserialize_parameters_aligned<I: IntoIterator<Item = usize>>(
|
|||
.ok_or(InstructionError::InvalidArgument)?,
|
||||
);
|
||||
if borrowed_account.get_lamports() != lamports {
|
||||
borrowed_account.set_lamports(lamports, feature_set)?;
|
||||
borrowed_account.set_lamports(lamports)?;
|
||||
}
|
||||
start += size_of::<u64>(); // lamports
|
||||
let post_len = LittleEndian::read_u64(
|
||||
|
@ -567,9 +554,9 @@ pub fn deserialize_parameters_aligned<I: IntoIterator<Item = usize>>(
|
|||
.ok_or(InstructionError::InvalidArgument)?;
|
||||
match borrowed_account
|
||||
.can_data_be_resized(post_len)
|
||||
.and_then(|_| borrowed_account.can_data_be_changed(feature_set))
|
||||
.and_then(|_| borrowed_account.can_data_be_changed())
|
||||
{
|
||||
Ok(()) => borrowed_account.set_data_from_slice(data, feature_set)?,
|
||||
Ok(()) => borrowed_account.set_data_from_slice(data)?,
|
||||
Err(err) if borrowed_account.get_data() != data => return Err(err),
|
||||
_ => {}
|
||||
}
|
||||
|
@ -583,14 +570,14 @@ pub fn deserialize_parameters_aligned<I: IntoIterator<Item = usize>>(
|
|||
.ok_or(InstructionError::InvalidArgument)?;
|
||||
match borrowed_account
|
||||
.can_data_be_resized(post_len)
|
||||
.and_then(|_| borrowed_account.can_data_be_changed(feature_set))
|
||||
.and_then(|_| borrowed_account.can_data_be_changed())
|
||||
{
|
||||
Ok(()) => {
|
||||
borrowed_account.set_data_length(post_len, feature_set)?;
|
||||
borrowed_account.set_data_length(post_len)?;
|
||||
let allocated_bytes = post_len.saturating_sub(pre_len);
|
||||
if allocated_bytes > 0 {
|
||||
borrowed_account
|
||||
.get_data_mut(feature_set)?
|
||||
.get_data_mut()?
|
||||
.get_mut(pre_len..pre_len.saturating_add(allocated_bytes))
|
||||
.ok_or(InstructionError::InvalidArgument)?
|
||||
.copy_from_slice(
|
||||
|
@ -608,18 +595,15 @@ pub fn deserialize_parameters_aligned<I: IntoIterator<Item = usize>>(
|
|||
start += size_of::<u64>(); // rent_epoch
|
||||
if borrowed_account.get_owner().to_bytes() != owner {
|
||||
// Change the owner at the end so that we are allowed to change the lamports and data before
|
||||
borrowed_account.set_owner(owner, feature_set)?;
|
||||
borrowed_account.set_owner(owner)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub(crate) fn account_data_region_memory_state(
|
||||
account: &BorrowedAccount<'_>,
|
||||
feature_set: &FeatureSet,
|
||||
) -> MemoryState {
|
||||
if account.can_data_be_changed(feature_set).is_ok() {
|
||||
pub(crate) fn account_data_region_memory_state(account: &BorrowedAccount<'_>) -> MemoryState {
|
||||
if account.can_data_be_changed().is_ok() {
|
||||
if account.is_shared() {
|
||||
MemoryState::Cow(account.get_index_in_transaction() as u64)
|
||||
} else {
|
||||
|
@ -744,7 +728,6 @@ mod tests {
|
|||
invoke_context.transaction_context,
|
||||
instruction_context,
|
||||
copy_account_data,
|
||||
&invoke_context.feature_set,
|
||||
);
|
||||
assert_eq!(
|
||||
serialization_result.as_ref().err(),
|
||||
|
@ -899,7 +882,6 @@ mod tests {
|
|||
invoke_context.transaction_context,
|
||||
instruction_context,
|
||||
copy_account_data,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -938,7 +920,7 @@ mod tests {
|
|||
assert_eq!(account.lamports(), account_info.lamports());
|
||||
assert_eq!(account.data(), &account_info.data.borrow()[..]);
|
||||
assert_eq!(account.owner(), account_info.owner);
|
||||
assert!(account_info.executable);
|
||||
assert_eq!(account.executable(), account_info.executable);
|
||||
assert_eq!(account.rent_epoch(), account_info.rent_epoch);
|
||||
|
||||
assert_eq!(
|
||||
|
@ -961,7 +943,6 @@ mod tests {
|
|||
copy_account_data,
|
||||
serialized.as_slice(),
|
||||
&accounts_metadata,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
.unwrap();
|
||||
for (index_in_transaction, (_key, original_account)) in
|
||||
|
@ -992,7 +973,6 @@ mod tests {
|
|||
invoke_context.transaction_context,
|
||||
instruction_context,
|
||||
copy_account_data,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
.unwrap();
|
||||
let mut serialized_regions = concat_regions(®ions);
|
||||
|
@ -1023,7 +1003,7 @@ mod tests {
|
|||
assert_eq!(account.lamports(), account_info.lamports());
|
||||
assert_eq!(account.data(), &account_info.data.borrow()[..]);
|
||||
assert_eq!(account.owner(), account_info.owner);
|
||||
assert!(account_info.executable);
|
||||
assert_eq!(account.executable(), account_info.executable);
|
||||
assert_eq!(account.rent_epoch(), account_info.rent_epoch);
|
||||
}
|
||||
|
||||
|
@ -1033,7 +1013,6 @@ mod tests {
|
|||
copy_account_data,
|
||||
serialized.as_slice(),
|
||||
&account_lengths,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
.unwrap();
|
||||
for (index_in_transaction, (_key, original_account)) in
|
||||
|
|
|
@ -8,7 +8,7 @@ use {
|
|||
memory_region::{MemoryRegion, MemoryState},
|
||||
},
|
||||
solana_sdk::{
|
||||
feature_set::{enable_bpf_loader_set_authority_checked_ix, FeatureSet},
|
||||
feature_set::enable_bpf_loader_set_authority_checked_ix,
|
||||
stable_layout::stable_instruction::StableInstruction,
|
||||
syscalls::{
|
||||
MAX_CPI_ACCOUNT_INFOS, MAX_CPI_INSTRUCTION_ACCOUNTS, MAX_CPI_INSTRUCTION_DATA_LEN,
|
||||
|
@ -883,7 +883,7 @@ where
|
|||
.transaction_context
|
||||
.get_key_of_account_at_index(instruction_account.index_in_transaction)?;
|
||||
|
||||
if callee_account.is_executable(&invoke_context.feature_set) {
|
||||
if callee_account.is_executable() {
|
||||
// Use the known account
|
||||
consume_compute_meter(
|
||||
invoke_context,
|
||||
|
@ -1139,7 +1139,6 @@ fn cpi_common<S: SyscallInvokeSigned>(
|
|||
caller_account,
|
||||
&callee_account,
|
||||
is_loader_deprecated,
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
@ -1180,7 +1179,7 @@ fn update_callee_account(
|
|||
direct_mapping: bool,
|
||||
) -> Result<(), Error> {
|
||||
if callee_account.get_lamports() != *caller_account.lamports {
|
||||
callee_account.set_lamports(*caller_account.lamports, &invoke_context.feature_set)?;
|
||||
callee_account.set_lamports(*caller_account.lamports)?;
|
||||
}
|
||||
|
||||
if direct_mapping {
|
||||
|
@ -1188,7 +1187,7 @@ fn update_callee_account(
|
|||
let post_len = *caller_account.ref_to_len_in_vm.get()? as usize;
|
||||
match callee_account
|
||||
.can_data_be_resized(post_len)
|
||||
.and_then(|_| callee_account.can_data_be_changed(&invoke_context.feature_set))
|
||||
.and_then(|_| callee_account.can_data_be_changed())
|
||||
{
|
||||
Ok(()) => {
|
||||
let realloc_bytes_used = post_len.saturating_sub(caller_account.original_data_len);
|
||||
|
@ -1196,7 +1195,7 @@ fn update_callee_account(
|
|||
if is_loader_deprecated && realloc_bytes_used > 0 {
|
||||
return Err(InstructionError::InvalidRealloc.into());
|
||||
}
|
||||
callee_account.set_data_length(post_len, &invoke_context.feature_set)?;
|
||||
callee_account.set_data_length(post_len)?;
|
||||
if realloc_bytes_used > 0 {
|
||||
let serialized_data = translate_slice::<u8>(
|
||||
memory_mapping,
|
||||
|
@ -1207,7 +1206,7 @@ fn update_callee_account(
|
|||
invoke_context.get_check_aligned(),
|
||||
)?;
|
||||
callee_account
|
||||
.get_data_mut(&invoke_context.feature_set)?
|
||||
.get_data_mut()?
|
||||
.get_mut(caller_account.original_data_len..post_len)
|
||||
.ok_or(SyscallError::InvalidLength)?
|
||||
.copy_from_slice(serialized_data);
|
||||
|
@ -1222,10 +1221,9 @@ fn update_callee_account(
|
|||
// The redundant check helps to avoid the expensive data comparison if we can
|
||||
match callee_account
|
||||
.can_data_be_resized(caller_account.serialized_data.len())
|
||||
.and_then(|_| callee_account.can_data_be_changed(&invoke_context.feature_set))
|
||||
.and_then(|_| callee_account.can_data_be_changed())
|
||||
{
|
||||
Ok(()) => callee_account
|
||||
.set_data_from_slice(caller_account.serialized_data, &invoke_context.feature_set)?,
|
||||
Ok(()) => callee_account.set_data_from_slice(caller_account.serialized_data)?,
|
||||
Err(err) if callee_account.get_data() != caller_account.serialized_data => {
|
||||
return Err(Box::new(err));
|
||||
}
|
||||
|
@ -1235,7 +1233,7 @@ fn update_callee_account(
|
|||
|
||||
// Change the owner at the end so that we are allowed to change the lamports and data before
|
||||
if callee_account.get_owner() != caller_account.owner {
|
||||
callee_account.set_owner(caller_account.owner.as_ref(), &invoke_context.feature_set)?;
|
||||
callee_account.set_owner(caller_account.owner.as_ref())?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -1246,7 +1244,6 @@ fn update_caller_account_perms(
|
|||
caller_account: &CallerAccount,
|
||||
callee_account: &BorrowedAccount<'_>,
|
||||
is_loader_deprecated: bool,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), Error> {
|
||||
let CallerAccount {
|
||||
original_data_len,
|
||||
|
@ -1256,10 +1253,9 @@ fn update_caller_account_perms(
|
|||
|
||||
let data_region = account_data_region(memory_mapping, *vm_data_addr, *original_data_len)?;
|
||||
if let Some(region) = data_region {
|
||||
region.state.set(account_data_region_memory_state(
|
||||
callee_account,
|
||||
feature_set,
|
||||
));
|
||||
region
|
||||
.state
|
||||
.set(account_data_region_memory_state(callee_account));
|
||||
}
|
||||
let realloc_region = account_realloc_region(
|
||||
memory_mapping,
|
||||
|
@ -1270,7 +1266,7 @@ fn update_caller_account_perms(
|
|||
if let Some(region) = realloc_region {
|
||||
region
|
||||
.state
|
||||
.set(if callee_account.can_data_be_changed(feature_set).is_ok() {
|
||||
.set(if callee_account.can_data_be_changed().is_ok() {
|
||||
MemoryState::Writable
|
||||
} else {
|
||||
MemoryState::Readable
|
||||
|
@ -1818,11 +1814,9 @@ mod tests {
|
|||
|
||||
let mut callee_account = borrow_instruction_account!(invoke_context, 0);
|
||||
|
||||
callee_account.set_lamports(42).unwrap();
|
||||
callee_account
|
||||
.set_lamports(42, &invoke_context.feature_set)
|
||||
.unwrap();
|
||||
callee_account
|
||||
.set_owner(Pubkey::new_unique().as_ref(), &invoke_context.feature_set)
|
||||
.set_owner(Pubkey::new_unique().as_ref())
|
||||
.unwrap();
|
||||
|
||||
update_caller_account(
|
||||
|
@ -1891,9 +1885,7 @@ mod tests {
|
|||
(b"foobazbad".to_vec(), MAX_PERMITTED_DATA_INCREASE - 3),
|
||||
] {
|
||||
assert_eq!(caller_account.serialized_data, callee_account.get_data());
|
||||
callee_account
|
||||
.set_data_from_slice(&new_value, &invoke_context.feature_set)
|
||||
.unwrap();
|
||||
callee_account.set_data_from_slice(&new_value).unwrap();
|
||||
|
||||
update_caller_account(
|
||||
&invoke_context,
|
||||
|
@ -1921,10 +1913,7 @@ mod tests {
|
|||
}
|
||||
|
||||
callee_account
|
||||
.set_data_length(
|
||||
original_data_len + MAX_PERMITTED_DATA_INCREASE,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
.set_data_length(original_data_len + MAX_PERMITTED_DATA_INCREASE)
|
||||
.unwrap();
|
||||
update_caller_account(
|
||||
&invoke_context,
|
||||
|
@ -1940,10 +1929,7 @@ mod tests {
|
|||
assert!(is_zeroed(&data_slice[data_len..]));
|
||||
|
||||
callee_account
|
||||
.set_data_length(
|
||||
original_data_len + MAX_PERMITTED_DATA_INCREASE + 1,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
.set_data_length(original_data_len + MAX_PERMITTED_DATA_INCREASE + 1)
|
||||
.unwrap();
|
||||
assert_matches!(
|
||||
update_caller_account(
|
||||
|
@ -1958,11 +1944,9 @@ mod tests {
|
|||
);
|
||||
|
||||
// close the account
|
||||
callee_account.set_data_length(0).unwrap();
|
||||
callee_account
|
||||
.set_data_length(0, &invoke_context.feature_set)
|
||||
.unwrap();
|
||||
callee_account
|
||||
.set_owner(system_program::id().as_ref(), &invoke_context.feature_set)
|
||||
.set_owner(system_program::id().as_ref())
|
||||
.unwrap();
|
||||
update_caller_account(
|
||||
&invoke_context,
|
||||
|
@ -2031,13 +2015,9 @@ mod tests {
|
|||
(vec![], 0), // check lower bound
|
||||
] {
|
||||
if change_ptr {
|
||||
callee_account
|
||||
.set_data(new_value, &invoke_context.feature_set)
|
||||
.unwrap();
|
||||
callee_account.set_data(new_value).unwrap();
|
||||
} else {
|
||||
callee_account
|
||||
.set_data_from_slice(&new_value, &invoke_context.feature_set)
|
||||
.unwrap();
|
||||
callee_account.set_data_from_slice(&new_value).unwrap();
|
||||
}
|
||||
|
||||
update_caller_account(
|
||||
|
@ -2107,10 +2087,7 @@ mod tests {
|
|||
}
|
||||
|
||||
callee_account
|
||||
.set_data_length(
|
||||
original_data_len + MAX_PERMITTED_DATA_INCREASE,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
.set_data_length(original_data_len + MAX_PERMITTED_DATA_INCREASE)
|
||||
.unwrap();
|
||||
update_caller_account(
|
||||
&invoke_context,
|
||||
|
@ -2128,10 +2105,7 @@ mod tests {
|
|||
);
|
||||
|
||||
callee_account
|
||||
.set_data_length(
|
||||
original_data_len + MAX_PERMITTED_DATA_INCREASE + 1,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
.set_data_length(original_data_len + MAX_PERMITTED_DATA_INCREASE + 1)
|
||||
.unwrap();
|
||||
assert_matches!(
|
||||
update_caller_account(
|
||||
|
@ -2146,11 +2120,9 @@ mod tests {
|
|||
);
|
||||
|
||||
// close the account
|
||||
callee_account.set_data_length(0).unwrap();
|
||||
callee_account
|
||||
.set_data_length(0, &invoke_context.feature_set)
|
||||
.unwrap();
|
||||
callee_account
|
||||
.set_owner(system_program::id().as_ref(), &invoke_context.feature_set)
|
||||
.set_owner(system_program::id().as_ref())
|
||||
.unwrap();
|
||||
update_caller_account(
|
||||
&invoke_context,
|
||||
|
@ -2493,9 +2465,7 @@ mod tests {
|
|||
// this is done when a writable account is mapped, and it ensures
|
||||
// through make_data_mut() that the account is made writable and resized
|
||||
// with enough padding to hold the realloc padding
|
||||
callee_account
|
||||
.get_data_mut(&invoke_context.feature_set)
|
||||
.unwrap();
|
||||
callee_account.get_data_mut().unwrap();
|
||||
|
||||
let serialized_data = translate_slice_mut::<u8>(
|
||||
&memory_mapping,
|
||||
|
|
|
@ -127,7 +127,7 @@ declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context|
|
|||
ic_msg!(invoke_context, "instruction data too large");
|
||||
return Err(InstructionError::InvalidInstructionData);
|
||||
}
|
||||
config_account.get_data_mut(&invoke_context.feature_set)?[..data.len()].copy_from_slice(data);
|
||||
config_account.get_data_mut()?[..data.len()].copy_from_slice(data);
|
||||
Ok(())
|
||||
});
|
||||
|
||||
|
|
|
@ -247,7 +247,7 @@ pub fn process_instruction_write(
|
|||
}
|
||||
let end_offset = (offset as usize).saturating_add(bytes.len());
|
||||
program
|
||||
.get_data_mut(&invoke_context.feature_set)?
|
||||
.get_data_mut()?
|
||||
.get_mut(
|
||||
LoaderV4State::program_data_offset().saturating_add(offset as usize)
|
||||
..LoaderV4State::program_data_offset().saturating_add(end_offset),
|
||||
|
@ -325,20 +325,19 @@ pub fn process_instruction_truncate(
|
|||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
let lamports_to_receive = program.get_lamports().saturating_sub(required_lamports);
|
||||
program.checked_sub_lamports(lamports_to_receive, &invoke_context.feature_set)?;
|
||||
recipient.checked_add_lamports(lamports_to_receive, &invoke_context.feature_set)?;
|
||||
program.checked_sub_lamports(lamports_to_receive)?;
|
||||
recipient.checked_add_lamports(lamports_to_receive)?;
|
||||
}
|
||||
std::cmp::Ordering::Equal => {}
|
||||
}
|
||||
if new_size == 0 {
|
||||
program.set_data_length(0, &invoke_context.feature_set)?;
|
||||
program.set_data_length(0)?;
|
||||
} else {
|
||||
program.set_data_length(
|
||||
LoaderV4State::program_data_offset().saturating_add(new_size as usize),
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
if is_initialization {
|
||||
let state = get_state_mut(program.get_data_mut(&invoke_context.feature_set)?)?;
|
||||
let state = get_state_mut(program.get_data_mut()?)?;
|
||||
state.slot = 0;
|
||||
state.status = LoaderV4Status::Retracted;
|
||||
state.authority_address = *authority_address;
|
||||
|
@ -432,12 +431,12 @@ pub fn process_instruction_deploy(
|
|||
let rent = invoke_context.get_sysvar_cache().get_rent()?;
|
||||
let required_lamports = rent.minimum_balance(source_program.get_data().len());
|
||||
let transfer_lamports = required_lamports.saturating_sub(program.get_lamports());
|
||||
program.set_data_from_slice(source_program.get_data(), &invoke_context.feature_set)?;
|
||||
source_program.set_data_length(0, &invoke_context.feature_set)?;
|
||||
source_program.checked_sub_lamports(transfer_lamports, &invoke_context.feature_set)?;
|
||||
program.checked_add_lamports(transfer_lamports, &invoke_context.feature_set)?;
|
||||
program.set_data_from_slice(source_program.get_data())?;
|
||||
source_program.set_data_length(0)?;
|
||||
source_program.checked_sub_lamports(transfer_lamports)?;
|
||||
program.checked_add_lamports(transfer_lamports)?;
|
||||
}
|
||||
let state = get_state_mut(program.get_data_mut(&invoke_context.feature_set)?)?;
|
||||
let state = get_state_mut(program.get_data_mut()?)?;
|
||||
state.slot = current_slot;
|
||||
state.status = LoaderV4Status::Deployed;
|
||||
|
||||
|
@ -486,7 +485,7 @@ pub fn process_instruction_retract(
|
|||
ic_logger_msg!(log_collector, "Program is not deployed");
|
||||
return Err(InstructionError::InvalidArgument);
|
||||
}
|
||||
let state = get_state_mut(program.get_data_mut(&invoke_context.feature_set)?)?;
|
||||
let state = get_state_mut(program.get_data_mut()?)?;
|
||||
state.status = LoaderV4Status::Retracted;
|
||||
Ok(())
|
||||
}
|
||||
|
@ -516,7 +515,7 @@ pub fn process_instruction_transfer_authority(
|
|||
ic_logger_msg!(log_collector, "New authority did not sign");
|
||||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
let state = get_state_mut(program.get_data_mut(&invoke_context.feature_set)?)?;
|
||||
let state = get_state_mut(program.get_data_mut()?)?;
|
||||
if let Some(new_authority_address) = new_authority_address {
|
||||
state.authority_address = new_authority_address;
|
||||
} else if matches!(state.status, LoaderV4Status::Deployed) {
|
||||
|
|
|
@ -38,7 +38,7 @@ use {
|
|||
bpf_loader,
|
||||
client::SyncClient,
|
||||
entrypoint::SUCCESS,
|
||||
feature_set::{self, FeatureSet},
|
||||
feature_set::FeatureSet,
|
||||
instruction::{AccountMeta, Instruction},
|
||||
message::Message,
|
||||
native_loader,
|
||||
|
@ -189,15 +189,11 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
|||
#[bench]
|
||||
fn bench_program_execute_noop(bencher: &mut Bencher) {
|
||||
let GenesisConfigInfo {
|
||||
mut genesis_config,
|
||||
genesis_config,
|
||||
mint_keypair,
|
||||
..
|
||||
} = create_genesis_config(50);
|
||||
|
||||
genesis_config
|
||||
.accounts
|
||||
.remove(&feature_set::deprecate_executable_meta_update_in_bpf_loader::id());
|
||||
|
||||
let bank = Bank::new_for_benches(&genesis_config);
|
||||
let (bank, bank_forks) = bank.wrap_with_bank_forks_for_tests();
|
||||
let mut bank_client = BankClient::new_shared(bank.clone());
|
||||
|
@ -261,7 +257,6 @@ fn bench_create_vm(bencher: &mut Bencher) {
|
|||
.get_current_instruction_context()
|
||||
.unwrap(),
|
||||
!direct_mapping, // copy_account_data,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
@ -296,7 +291,6 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
|||
.get_current_instruction_context()
|
||||
.unwrap(),
|
||||
!direct_mapping, // copy_account_data
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
|
|
@ -73,13 +73,7 @@ declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context|
|
|||
Ok(StakeInstruction::Initialize(authorized, lockup)) => {
|
||||
let mut me = get_stake_account()?;
|
||||
let rent = get_sysvar_with_account_check::rent(invoke_context, instruction_context, 1)?;
|
||||
initialize(
|
||||
&mut me,
|
||||
&authorized,
|
||||
&lockup,
|
||||
&rent,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
initialize(&mut me, &authorized, &lockup, &rent)
|
||||
}
|
||||
Ok(StakeInstruction::Authorize(authorized_pubkey, stake_authorize)) => {
|
||||
let mut me = get_stake_account()?;
|
||||
|
@ -96,7 +90,6 @@ declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context|
|
|||
stake_authorize,
|
||||
&clock,
|
||||
custodian_pubkey,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
}
|
||||
Ok(StakeInstruction::AuthorizeWithSeed(args)) => {
|
||||
|
@ -118,7 +111,6 @@ declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context|
|
|||
args.stake_authorize,
|
||||
&clock,
|
||||
custodian_pubkey,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
}
|
||||
Ok(StakeInstruction::DelegateStake) => {
|
||||
|
@ -221,7 +213,6 @@ declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context|
|
|||
None
|
||||
},
|
||||
new_warmup_cooldown_rate_epoch(invoke_context),
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
}
|
||||
Ok(StakeInstruction::Deactivate) => {
|
||||
|
@ -233,13 +224,7 @@ declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context|
|
|||
Ok(StakeInstruction::SetLockup(lockup)) => {
|
||||
let mut me = get_stake_account()?;
|
||||
let clock = invoke_context.get_sysvar_cache().get_clock()?;
|
||||
set_lockup(
|
||||
&mut me,
|
||||
&lockup,
|
||||
&signers,
|
||||
&clock,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
set_lockup(&mut me, &lockup, &signers, &clock)
|
||||
}
|
||||
Ok(StakeInstruction::InitializeChecked) => {
|
||||
let mut me = get_stake_account()?;
|
||||
|
@ -260,13 +245,7 @@ declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context|
|
|||
};
|
||||
|
||||
let rent = get_sysvar_with_account_check::rent(invoke_context, instruction_context, 1)?;
|
||||
initialize(
|
||||
&mut me,
|
||||
&authorized,
|
||||
&Lockup::default(),
|
||||
&rent,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
initialize(&mut me, &authorized, &Lockup::default(), &rent)
|
||||
}
|
||||
Ok(StakeInstruction::AuthorizeChecked(stake_authorize)) => {
|
||||
let mut me = get_stake_account()?;
|
||||
|
@ -289,7 +268,6 @@ declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context|
|
|||
stake_authorize,
|
||||
&clock,
|
||||
custodian_pubkey,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
}
|
||||
Ok(StakeInstruction::AuthorizeCheckedWithSeed(args)) => {
|
||||
|
@ -318,7 +296,6 @@ declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context|
|
|||
args.stake_authorize,
|
||||
&clock,
|
||||
custodian_pubkey,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
}
|
||||
Ok(StakeInstruction::SetLockupChecked(lockup_checked)) => {
|
||||
|
@ -332,13 +309,7 @@ declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context|
|
|||
custodian: custodian_pubkey.cloned(),
|
||||
};
|
||||
let clock = invoke_context.get_sysvar_cache().get_clock()?;
|
||||
set_lockup(
|
||||
&mut me,
|
||||
&lockup,
|
||||
&signers,
|
||||
&clock,
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
set_lockup(&mut me, &lockup, &signers, &clock)
|
||||
}
|
||||
Ok(StakeInstruction::GetMinimumDelegation) => {
|
||||
let feature_set = invoke_context.feature_set.as_ref();
|
||||
|
|
|
@ -149,7 +149,6 @@ pub fn initialize(
|
|||
authorized: &Authorized,
|
||||
lockup: &Lockup,
|
||||
rent: &Rent,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
if stake_account.get_data().len() != StakeStateV2::size_of() {
|
||||
return Err(InstructionError::InvalidAccountData);
|
||||
|
@ -158,14 +157,11 @@ pub fn initialize(
|
|||
if let StakeStateV2::Uninitialized = stake_account.get_state()? {
|
||||
let rent_exempt_reserve = rent.minimum_balance(stake_account.get_data().len());
|
||||
if stake_account.get_lamports() >= rent_exempt_reserve {
|
||||
stake_account.set_state(
|
||||
&StakeStateV2::Initialized(Meta {
|
||||
rent_exempt_reserve,
|
||||
authorized: *authorized,
|
||||
lockup: *lockup,
|
||||
}),
|
||||
feature_set,
|
||||
)
|
||||
stake_account.set_state(&StakeStateV2::Initialized(Meta {
|
||||
rent_exempt_reserve,
|
||||
authorized: *authorized,
|
||||
lockup: *lockup,
|
||||
}))
|
||||
} else {
|
||||
Err(InstructionError::InsufficientFunds)
|
||||
}
|
||||
|
@ -184,7 +180,6 @@ pub fn authorize(
|
|||
stake_authorize: StakeAuthorize,
|
||||
clock: &Clock,
|
||||
custodian: Option<&Pubkey>,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
match stake_account.get_state()? {
|
||||
StakeStateV2::Stake(mut meta, stake, stake_flags) => {
|
||||
|
@ -194,7 +189,7 @@ pub fn authorize(
|
|||
stake_authorize,
|
||||
Some((&meta.lockup, clock, custodian)),
|
||||
)?;
|
||||
stake_account.set_state(&StakeStateV2::Stake(meta, stake, stake_flags), feature_set)
|
||||
stake_account.set_state(&StakeStateV2::Stake(meta, stake, stake_flags))
|
||||
}
|
||||
StakeStateV2::Initialized(mut meta) => {
|
||||
meta.authorized.authorize(
|
||||
|
@ -203,7 +198,7 @@ pub fn authorize(
|
|||
stake_authorize,
|
||||
Some((&meta.lockup, clock, custodian)),
|
||||
)?;
|
||||
stake_account.set_state(&StakeStateV2::Initialized(meta), feature_set)
|
||||
stake_account.set_state(&StakeStateV2::Initialized(meta))
|
||||
}
|
||||
_ => Err(InstructionError::InvalidAccountData),
|
||||
}
|
||||
|
@ -221,7 +216,6 @@ pub fn authorize_with_seed(
|
|||
stake_authorize: StakeAuthorize,
|
||||
clock: &Clock,
|
||||
custodian: Option<&Pubkey>,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
let mut signers = HashSet::default();
|
||||
if instruction_context.is_instruction_account_signer(authority_base_index)? {
|
||||
|
@ -242,7 +236,6 @@ pub fn authorize_with_seed(
|
|||
stake_authorize,
|
||||
clock,
|
||||
custodian,
|
||||
feature_set,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -280,10 +273,7 @@ pub fn delegate(
|
|||
&vote_state?.convert_to_current(),
|
||||
clock.epoch,
|
||||
);
|
||||
stake_account.set_state(
|
||||
&StakeStateV2::Stake(meta, stake, StakeFlags::empty()),
|
||||
feature_set,
|
||||
)
|
||||
stake_account.set_state(&StakeStateV2::Stake(meta, stake, StakeFlags::empty()))
|
||||
}
|
||||
StakeStateV2::Stake(meta, mut stake, stake_flags) => {
|
||||
meta.authorized.check(signers, StakeAuthorize::Staker)?;
|
||||
|
@ -298,7 +288,7 @@ pub fn delegate(
|
|||
clock,
|
||||
stake_history,
|
||||
)?;
|
||||
stake_account.set_state(&StakeStateV2::Stake(meta, stake, stake_flags), feature_set)
|
||||
stake_account.set_state(&StakeStateV2::Stake(meta, stake, stake_flags))
|
||||
}
|
||||
_ => Err(InstructionError::InvalidAccountData),
|
||||
}
|
||||
|
@ -354,10 +344,7 @@ pub fn deactivate(
|
|||
if let StakeStateV2::Stake(meta, mut stake, mut stake_flags) = stake_account.get_state()? {
|
||||
meta.authorized.check(signers, StakeAuthorize::Staker)?;
|
||||
deactivate_stake(invoke_context, &mut stake, &mut stake_flags, clock.epoch)?;
|
||||
stake_account.set_state(
|
||||
&StakeStateV2::Stake(meta, stake, stake_flags),
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
stake_account.set_state(&StakeStateV2::Stake(meta, stake, stake_flags))
|
||||
} else {
|
||||
Err(InstructionError::InvalidAccountData)
|
||||
}
|
||||
|
@ -368,16 +355,15 @@ pub fn set_lockup(
|
|||
lockup: &LockupArgs,
|
||||
signers: &HashSet<Pubkey>,
|
||||
clock: &Clock,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
match stake_account.get_state()? {
|
||||
StakeStateV2::Initialized(mut meta) => {
|
||||
meta.set_lockup(lockup, signers, clock)?;
|
||||
stake_account.set_state(&StakeStateV2::Initialized(meta), feature_set)
|
||||
stake_account.set_state(&StakeStateV2::Initialized(meta))
|
||||
}
|
||||
StakeStateV2::Stake(mut meta, stake, stake_flags) => {
|
||||
meta.set_lockup(lockup, signers, clock)?;
|
||||
stake_account.set_state(&StakeStateV2::Stake(meta, stake, stake_flags), feature_set)
|
||||
stake_account.set_state(&StakeStateV2::Stake(meta, stake, stake_flags))
|
||||
}
|
||||
_ => Err(InstructionError::InvalidAccountData),
|
||||
}
|
||||
|
@ -481,17 +467,11 @@ pub fn split(
|
|||
|
||||
let mut stake_account = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, stake_account_index)?;
|
||||
stake_account.set_state(
|
||||
&StakeStateV2::Stake(meta, stake, stake_flags),
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
stake_account.set_state(&StakeStateV2::Stake(meta, stake, stake_flags))?;
|
||||
drop(stake_account);
|
||||
let mut split = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, split_index)?;
|
||||
split.set_state(
|
||||
&StakeStateV2::Stake(split_meta, split_stake, stake_flags),
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
split.set_state(&StakeStateV2::Stake(split_meta, split_stake, stake_flags))?;
|
||||
}
|
||||
StakeStateV2::Initialized(meta) => {
|
||||
meta.authorized.check(signers, StakeAuthorize::Staker)?;
|
||||
|
@ -510,10 +490,7 @@ pub fn split(
|
|||
split_meta.rent_exempt_reserve = validated_split_info.destination_rent_exempt_reserve;
|
||||
let mut split = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, split_index)?;
|
||||
split.set_state(
|
||||
&StakeStateV2::Initialized(split_meta),
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
split.set_state(&StakeStateV2::Initialized(split_meta))?;
|
||||
}
|
||||
StakeStateV2::Uninitialized => {
|
||||
let stake_pubkey = transaction_context.get_key_of_account_at_index(
|
||||
|
@ -531,17 +508,17 @@ pub fn split(
|
|||
let mut stake_account = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, stake_account_index)?;
|
||||
if lamports == stake_account.get_lamports() {
|
||||
stake_account.set_state(&StakeStateV2::Uninitialized, &invoke_context.feature_set)?;
|
||||
stake_account.set_state(&StakeStateV2::Uninitialized)?;
|
||||
}
|
||||
drop(stake_account);
|
||||
|
||||
let mut split =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, split_index)?;
|
||||
split.checked_add_lamports(lamports, &invoke_context.feature_set)?;
|
||||
split.checked_add_lamports(lamports)?;
|
||||
drop(split);
|
||||
let mut stake_account = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, stake_account_index)?;
|
||||
stake_account.checked_sub_lamports(lamports, &invoke_context.feature_set)?;
|
||||
stake_account.checked_sub_lamports(lamports)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -597,16 +574,16 @@ pub fn merge(
|
|||
|
||||
ic_msg!(invoke_context, "Merging stake accounts");
|
||||
if let Some(merged_state) = stake_merge_kind.merge(invoke_context, source_merge_kind, clock)? {
|
||||
stake_account.set_state(&merged_state, &invoke_context.feature_set)?;
|
||||
stake_account.set_state(&merged_state)?;
|
||||
}
|
||||
|
||||
// Source is about to be drained, deinitialize its state
|
||||
source_account.set_state(&StakeStateV2::Uninitialized, &invoke_context.feature_set)?;
|
||||
source_account.set_state(&StakeStateV2::Uninitialized)?;
|
||||
|
||||
// Drain the source stake account
|
||||
let lamports = source_account.get_lamports();
|
||||
source_account.checked_sub_lamports(lamports, &invoke_context.feature_set)?;
|
||||
stake_account.checked_add_lamports(lamports, &invoke_context.feature_set)?;
|
||||
source_account.checked_sub_lamports(lamports)?;
|
||||
stake_account.checked_add_lamports(lamports)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -698,9 +675,8 @@ pub fn redelegate(
|
|||
deactivate(invoke_context, stake_account, &clock, signers)?;
|
||||
|
||||
// transfer the effective stake to the uninitialized stake account
|
||||
stake_account.checked_sub_lamports(effective_stake, &invoke_context.feature_set)?;
|
||||
uninitialized_stake_account
|
||||
.checked_add_lamports(effective_stake, &invoke_context.feature_set)?;
|
||||
stake_account.checked_sub_lamports(effective_stake)?;
|
||||
uninitialized_stake_account.checked_add_lamports(effective_stake)?;
|
||||
|
||||
// initialize and schedule `uninitialized_stake_account` for activation
|
||||
let sysvar_cache = invoke_context.get_sysvar_cache();
|
||||
|
@ -714,19 +690,16 @@ pub fn redelegate(
|
|||
&uninitialized_stake_meta,
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
uninitialized_stake_account.set_state(
|
||||
&StakeStateV2::Stake(
|
||||
uninitialized_stake_meta,
|
||||
new_stake(
|
||||
stake_amount,
|
||||
&vote_pubkey,
|
||||
&vote_state.convert_to_current(),
|
||||
clock.epoch,
|
||||
),
|
||||
StakeFlags::MUST_FULLY_ACTIVATE_BEFORE_DEACTIVATION_IS_PERMITTED,
|
||||
uninitialized_stake_account.set_state(&StakeStateV2::Stake(
|
||||
uninitialized_stake_meta,
|
||||
new_stake(
|
||||
stake_amount,
|
||||
&vote_pubkey,
|
||||
&vote_state.convert_to_current(),
|
||||
clock.epoch,
|
||||
),
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
StakeFlags::MUST_FULLY_ACTIVATE_BEFORE_DEACTIVATION_IS_PERMITTED,
|
||||
))?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -743,7 +716,6 @@ pub fn withdraw(
|
|||
withdraw_authority_index: IndexOfAccount,
|
||||
custodian_index: Option<IndexOfAccount>,
|
||||
new_rate_activation_epoch: Option<Epoch>,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
let withdraw_authority_pubkey = transaction_context.get_key_of_account_at_index(
|
||||
instruction_context
|
||||
|
@ -828,14 +800,14 @@ pub fn withdraw(
|
|||
|
||||
// Deinitialize state upon zero balance
|
||||
if lamports == stake_account.get_lamports() {
|
||||
stake_account.set_state(&StakeStateV2::Uninitialized, feature_set)?;
|
||||
stake_account.set_state(&StakeStateV2::Uninitialized)?;
|
||||
}
|
||||
|
||||
stake_account.checked_sub_lamports(lamports, feature_set)?;
|
||||
stake_account.checked_sub_lamports(lamports)?;
|
||||
drop(stake_account);
|
||||
let mut to =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, to_index)?;
|
||||
to.checked_add_lamports(lamports, feature_set)?;
|
||||
to.checked_add_lamports(lamports)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -883,10 +855,7 @@ pub(crate) fn deactivate_delinquent(
|
|||
// voted in the last `MINIMUM_DELINQUENT_EPOCHS_FOR_DEACTIVATION`
|
||||
if eligible_for_deactivate_delinquent(&delinquent_vote_state.epoch_credits, current_epoch) {
|
||||
deactivate_stake(invoke_context, &mut stake, &mut stake_flags, current_epoch)?;
|
||||
stake_account.set_state(
|
||||
&StakeStateV2::Stake(meta, stake, stake_flags),
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
stake_account.set_state(&StakeStateV2::Stake(meta, stake, stake_flags))
|
||||
} else {
|
||||
Err(StakeError::MinimumDelinquentEpochsForDeactivationNotMet.into())
|
||||
}
|
||||
|
|
|
@ -56,10 +56,7 @@ pub fn advance_nonce_account(
|
|||
next_durable_nonce,
|
||||
invoke_context.lamports_per_signature,
|
||||
);
|
||||
account.set_state(
|
||||
&Versions::new(State::Initialized(new_data)),
|
||||
&invoke_context.feature_set,
|
||||
)
|
||||
account.set_state(&Versions::new(State::Initialized(new_data)))
|
||||
}
|
||||
State::Uninitialized => {
|
||||
ic_msg!(
|
||||
|
@ -117,10 +114,7 @@ pub fn withdraw_nonce_account(
|
|||
);
|
||||
return Err(SystemError::NonceBlockhashNotExpired.into());
|
||||
}
|
||||
from.set_state(
|
||||
&Versions::new(State::Uninitialized),
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
from.set_state(&Versions::new(State::Uninitialized))?;
|
||||
} else {
|
||||
let min_balance = rent.minimum_balance(from.get_data().len());
|
||||
let amount = checked_add(lamports, min_balance)?;
|
||||
|
@ -147,11 +141,11 @@ pub fn withdraw_nonce_account(
|
|||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
|
||||
from.checked_sub_lamports(lamports, &invoke_context.feature_set)?;
|
||||
from.checked_sub_lamports(lamports)?;
|
||||
drop(from);
|
||||
let mut to = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, to_account_index)?;
|
||||
to.checked_add_lamports(lamports, &invoke_context.feature_set)?;
|
||||
to.checked_add_lamports(lamports)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -190,7 +184,7 @@ pub fn initialize_nonce_account(
|
|||
invoke_context.lamports_per_signature,
|
||||
);
|
||||
let state = State::Initialized(data);
|
||||
account.set_state(&Versions::new(state), &invoke_context.feature_set)
|
||||
account.set_state(&Versions::new(state))
|
||||
}
|
||||
State::Initialized(_) => {
|
||||
ic_msg!(
|
||||
|
@ -221,7 +215,7 @@ pub fn authorize_nonce_account(
|
|||
.get_state::<Versions>()?
|
||||
.authorize(signers, *nonce_authority)
|
||||
{
|
||||
Ok(versions) => account.set_state(&versions, &invoke_context.feature_set),
|
||||
Ok(versions) => account.set_state(&versions),
|
||||
Err(AuthorizeNonceError::Uninitialized) => {
|
||||
ic_msg!(
|
||||
invoke_context,
|
||||
|
@ -1002,9 +996,7 @@ mod test {
|
|||
let mut nonce_account = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, NONCE_ACCOUNT_INDEX)
|
||||
.unwrap();
|
||||
nonce_account
|
||||
.checked_sub_lamports(42 * 2, &invoke_context.feature_set)
|
||||
.unwrap();
|
||||
nonce_account.checked_sub_lamports(42 * 2).unwrap();
|
||||
set_invoke_context_blockhash!(invoke_context, 63);
|
||||
let authorized = *nonce_account.get_key();
|
||||
let result =
|
||||
|
|
|
@ -104,7 +104,7 @@ fn allocate(
|
|||
return Err(SystemError::InvalidAccountDataLength.into());
|
||||
}
|
||||
|
||||
account.set_data_length(space as usize, &invoke_context.feature_set)?;
|
||||
account.set_data_length(space as usize)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ fn assign(
|
|||
return Err(InstructionError::MissingRequiredSignature);
|
||||
}
|
||||
|
||||
account.set_owner(&owner.to_bytes(), &invoke_context.feature_set)
|
||||
account.set_owner(&owner.to_bytes())
|
||||
}
|
||||
|
||||
fn allocate_and_assign(
|
||||
|
@ -203,11 +203,11 @@ fn transfer_verified(
|
|||
return Err(SystemError::ResultWithNegativeLamports.into());
|
||||
}
|
||||
|
||||
from.checked_sub_lamports(lamports, &invoke_context.feature_set)?;
|
||||
from.checked_sub_lamports(lamports)?;
|
||||
drop(from);
|
||||
let mut to = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, to_account_index)?;
|
||||
to.checked_add_lamports(lamports, &invoke_context.feature_set)?;
|
||||
to.checked_add_lamports(lamports)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -481,9 +481,7 @@ declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context|
|
|||
let nonce_versions: nonce::state::Versions = nonce_account.get_state()?;
|
||||
match nonce_versions.upgrade() {
|
||||
None => Err(InstructionError::InvalidArgument),
|
||||
Some(nonce_versions) => {
|
||||
nonce_account.set_state(&nonce_versions, &invoke_context.feature_set)
|
||||
}
|
||||
Some(nonce_versions) => nonce_account.set_state(&nonce_versions),
|
||||
}
|
||||
}
|
||||
SystemInstruction::Allocate { space } => {
|
||||
|
@ -2065,4 +2063,54 @@ mod tests {
|
|||
upgraded_nonce_account
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_assign_native_loader_and_transfer() {
|
||||
for size in [0, 10] {
|
||||
let pubkey = Pubkey::new_unique();
|
||||
let account = AccountSharedData::new(100, size, &system_program::id());
|
||||
let accounts = process_instruction(
|
||||
&bincode::serialize(&SystemInstruction::Assign {
|
||||
owner: solana_sdk::native_loader::id(),
|
||||
})
|
||||
.unwrap(),
|
||||
vec![(pubkey, account.clone())],
|
||||
vec![AccountMeta {
|
||||
pubkey,
|
||||
is_signer: true,
|
||||
is_writable: true,
|
||||
}],
|
||||
Ok(()),
|
||||
);
|
||||
assert_eq!(accounts[0].owner(), &solana_sdk::native_loader::id());
|
||||
assert_eq!(accounts[0].lamports(), 100);
|
||||
|
||||
let pubkey2 = Pubkey::new_unique();
|
||||
let accounts = process_instruction(
|
||||
&bincode::serialize(&SystemInstruction::Transfer { lamports: 50 }).unwrap(),
|
||||
vec![
|
||||
(
|
||||
pubkey2,
|
||||
AccountSharedData::new(100, 0, &system_program::id()),
|
||||
),
|
||||
(pubkey, accounts[0].clone()),
|
||||
],
|
||||
vec![
|
||||
AccountMeta {
|
||||
pubkey: pubkey2,
|
||||
is_signer: true,
|
||||
is_writable: true,
|
||||
},
|
||||
AccountMeta {
|
||||
pubkey,
|
||||
is_signer: false,
|
||||
is_writable: true,
|
||||
},
|
||||
],
|
||||
Ok(()),
|
||||
);
|
||||
assert_eq!(accounts[1].owner(), &solana_sdk::native_loader::id());
|
||||
assert_eq!(accounts[1].lamports(), 150);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -156,24 +156,22 @@ fn set_vote_account_state(
|
|||
&& (!vote_account
|
||||
.is_rent_exempt_at_data_length(VoteStateVersions::vote_state_size_of(true))
|
||||
|| vote_account
|
||||
.set_data_length(VoteStateVersions::vote_state_size_of(true), feature_set)
|
||||
.set_data_length(VoteStateVersions::vote_state_size_of(true))
|
||||
.is_err())
|
||||
{
|
||||
// Account cannot be resized to the size of a vote state as it will not be rent exempt, or failed to be
|
||||
// resized for other reasons. So store the V1_14_11 version.
|
||||
return vote_account.set_state(
|
||||
&VoteStateVersions::V1_14_11(Box::new(VoteState1_14_11::from(vote_state))),
|
||||
feature_set,
|
||||
);
|
||||
return vote_account.set_state(&VoteStateVersions::V1_14_11(Box::new(
|
||||
VoteState1_14_11::from(vote_state),
|
||||
)));
|
||||
}
|
||||
// Vote account is large enough to store the newest version of vote state
|
||||
vote_account.set_state(&VoteStateVersions::new_current(vote_state), feature_set)
|
||||
vote_account.set_state(&VoteStateVersions::new_current(vote_state))
|
||||
// Else when the vote_state_add_vote_latency feature is not enabled, then the V1_14_11 version is stored
|
||||
} else {
|
||||
vote_account.set_state(
|
||||
&VoteStateVersions::V1_14_11(Box::new(VoteState1_14_11::from(vote_state))),
|
||||
feature_set,
|
||||
)
|
||||
vote_account.set_state(&VoteStateVersions::V1_14_11(Box::new(
|
||||
VoteState1_14_11::from(vote_state),
|
||||
)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1023,11 +1021,11 @@ pub fn withdraw<S: std::hash::BuildHasher>(
|
|||
}
|
||||
}
|
||||
|
||||
vote_account.checked_sub_lamports(lamports, feature_set)?;
|
||||
vote_account.checked_sub_lamports(lamports)?;
|
||||
drop(vote_account);
|
||||
let mut to_account = instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, to_account_index)?;
|
||||
to_account.checked_add_lamports(lamports, feature_set)?;
|
||||
to_account.checked_add_lamports(lamports)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -1373,7 +1371,7 @@ mod tests {
|
|||
// Test that when the feature is enabled, if the vote account does have sufficient lamports, the
|
||||
// new vote state is written out
|
||||
assert_eq!(
|
||||
borrowed_account.set_lamports(rent.minimum_balance(VoteState::size_of()), &feature_set),
|
||||
borrowed_account.set_lamports(rent.minimum_balance(VoteState::size_of()),),
|
||||
Ok(())
|
||||
);
|
||||
assert_eq!(
|
||||
|
|
|
@ -130,8 +130,7 @@ where
|
|||
return Err(InstructionError::InvalidAccountData);
|
||||
}
|
||||
|
||||
proof_context_account
|
||||
.set_data_from_slice(&context_state_data, &invoke_context.feature_set)?;
|
||||
proof_context_account.set_data_from_slice(&context_state_data)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
@ -173,13 +172,10 @@ fn process_close_proof_context(invoke_context: &mut InvokeContext) -> Result<(),
|
|||
|
||||
let mut destination_account =
|
||||
instruction_context.try_borrow_instruction_account(transaction_context, 1)?;
|
||||
destination_account.checked_add_lamports(
|
||||
proof_context_account.get_lamports(),
|
||||
&invoke_context.feature_set,
|
||||
)?;
|
||||
proof_context_account.set_lamports(0, &invoke_context.feature_set)?;
|
||||
proof_context_account.set_data_length(0, &invoke_context.feature_set)?;
|
||||
proof_context_account.set_owner(system_program::id().as_ref(), &invoke_context.feature_set)?;
|
||||
destination_account.checked_add_lamports(proof_context_account.get_lamports())?;
|
||||
proof_context_account.set_lamports(0)?;
|
||||
proof_context_account.set_data_length(0)?;
|
||||
proof_context_account.set_owner(system_program::id().as_ref())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -107,9 +107,8 @@ use {
|
|||
},
|
||||
solana_sdk::{
|
||||
account::{
|
||||
create_account_shared_data_with_fields as create_account, create_executable_meta,
|
||||
from_account, Account, AccountSharedData, InheritableAccountFields, ReadableAccount,
|
||||
WritableAccount,
|
||||
create_account_shared_data_with_fields as create_account, from_account, Account,
|
||||
AccountSharedData, InheritableAccountFields, ReadableAccount, WritableAccount,
|
||||
},
|
||||
clock::{
|
||||
BankId, Epoch, Slot, SlotCount, SlotIndex, UnixTimestamp, DEFAULT_HASHES_PER_TICK,
|
||||
|
@ -3955,12 +3954,10 @@ impl Bank {
|
|||
// Add a bogus executable account, which will be loaded and ignored.
|
||||
let (lamports, rent_epoch) = self.inherit_specially_retained_account_fields(&None);
|
||||
|
||||
// Mock account_data with executable_meta so that the account is executable.
|
||||
let account_data = create_executable_meta(&owner);
|
||||
let account = AccountSharedData::from(Account {
|
||||
lamports,
|
||||
owner,
|
||||
data: account_data.to_vec(),
|
||||
data: vec![],
|
||||
executable: true,
|
||||
rent_epoch,
|
||||
});
|
||||
|
|
|
@ -1051,7 +1051,6 @@ fn test_rent_exempt_executable_account() {
|
|||
let mut account = AccountSharedData::new(account_balance, 0, &solana_sdk::pubkey::new_rand());
|
||||
account.set_executable(true);
|
||||
account.set_owner(bpf_loader_upgradeable::id());
|
||||
account.set_data(create_executable_meta(account.owner()).to_vec());
|
||||
bank.store_account(&account_pubkey, &account);
|
||||
|
||||
let transfer_lamports = 1;
|
||||
|
@ -1089,10 +1088,10 @@ fn test_rent_complex() {
|
|||
MockInstruction::Deduction => {
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.checked_add_lamports(1, &invoke_context.feature_set)?;
|
||||
.checked_add_lamports(1)?;
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 2)?
|
||||
.checked_sub_lamports(1, &invoke_context.feature_set)?;
|
||||
.checked_sub_lamports(1)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -5994,16 +5993,16 @@ fn test_transaction_with_duplicate_accounts_in_instruction() {
|
|||
let lamports = u64::from_le_bytes(instruction_data.try_into().unwrap());
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 2)?
|
||||
.checked_sub_lamports(lamports, &invoke_context.feature_set)?;
|
||||
.checked_sub_lamports(lamports)?;
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.checked_add_lamports(lamports, &invoke_context.feature_set)?;
|
||||
.checked_add_lamports(lamports)?;
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 0)?
|
||||
.checked_sub_lamports(lamports, &invoke_context.feature_set)?;
|
||||
.checked_sub_lamports(lamports)?;
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.checked_add_lamports(lamports, &invoke_context.feature_set)?;
|
||||
.checked_add_lamports(lamports)?;
|
||||
Ok(())
|
||||
});
|
||||
|
||||
|
@ -6473,25 +6472,26 @@ fn test_bank_hash_consistency() {
|
|||
if bank.slot == 0 {
|
||||
assert_eq!(
|
||||
bank.hash().to_string(),
|
||||
"3VqF5pMe3XABLqzUaYw2UVXfAokMJgMkrdfvneFQkHbB",
|
||||
"i5hGiQ3WtEehNrvhbfPFkUdm267t18fSpujcYtkBioW",
|
||||
);
|
||||
}
|
||||
|
||||
if bank.slot == 32 {
|
||||
assert_eq!(
|
||||
bank.hash().to_string(),
|
||||
"B8GsaBJ9aJrQcbhTTfgNVuV4uwb4v8nKT86HUjDLvNgk",
|
||||
"7NmBtNvbhoqzatJv8NgBs84qWrm4ZhpuC75DCpbqwiS"
|
||||
);
|
||||
}
|
||||
if bank.slot == 64 {
|
||||
assert_eq!(
|
||||
bank.hash().to_string(),
|
||||
"Eg9VRE3zUwarxWyHXhitX9wLkg1vfNeiVqVQxSif6qEC"
|
||||
"A1jjuUaENeDcsSvwejFGaZ5zWmnJ77doSzqdKtfzpoFk"
|
||||
);
|
||||
}
|
||||
if bank.slot == 128 {
|
||||
assert_eq!(
|
||||
bank.hash().to_string(),
|
||||
"5rLmK24zyxdeb8aLn5LDEnHLDQmxRd5gWZDVJGgsFX1c"
|
||||
"ApnMkFt5Bs4yDJ8S2CCPsQRL1He6vWXw6vMzAyc5i811"
|
||||
);
|
||||
break;
|
||||
}
|
||||
|
@ -6507,7 +6507,7 @@ fn test_same_program_id_uses_unique_executable_accounts() {
|
|||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||
instruction_context
|
||||
.try_borrow_program_account(transaction_context, 0)?
|
||||
.set_data_length(2, &invoke_context.feature_set)
|
||||
.set_data_length(2)
|
||||
});
|
||||
|
||||
let (genesis_config, mint_keypair) = create_genesis_config(50000);
|
||||
|
@ -9477,7 +9477,7 @@ fn test_transfer_sysvar() {
|
|||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.set_data(vec![0; 40], &invoke_context.feature_set)?;
|
||||
.set_data(vec![0; 40])?;
|
||||
Ok(())
|
||||
});
|
||||
|
||||
|
@ -10321,10 +10321,10 @@ declare_process_instruction!(MockTransferBuiltin, 1, |invoke_context| {
|
|||
MockTransferInstruction::Transfer(amount) => {
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.checked_sub_lamports(amount, &invoke_context.feature_set)?;
|
||||
.checked_sub_lamports(amount)?;
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 2)?
|
||||
.checked_add_lamports(amount, &invoke_context.feature_set)?;
|
||||
.checked_add_lamports(amount)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -11034,7 +11034,7 @@ declare_process_instruction!(MockReallocBuiltin, 1, |invoke_context| {
|
|||
// Set data length
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.set_data_length(new_size, &invoke_context.feature_set)?;
|
||||
.set_data_length(new_size)?;
|
||||
|
||||
// set balance
|
||||
let current_balance = instruction_context
|
||||
|
@ -11045,17 +11045,17 @@ declare_process_instruction!(MockReallocBuiltin, 1, |invoke_context| {
|
|||
if diff_balance.is_positive() {
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 0)?
|
||||
.checked_sub_lamports(amount, &invoke_context.feature_set)?;
|
||||
.checked_sub_lamports(amount)?;
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.set_lamports(new_balance, &invoke_context.feature_set)?;
|
||||
.set_lamports(new_balance)?;
|
||||
} else {
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 0)?
|
||||
.checked_add_lamports(amount, &invoke_context.feature_set)?;
|
||||
.checked_add_lamports(amount)?;
|
||||
instruction_context
|
||||
.try_borrow_instruction_account(transaction_context, 1)?
|
||||
.set_lamports(new_balance, &invoke_context.feature_set)?;
|
||||
.set_lamports(new_balance)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -6,9 +6,8 @@ use {
|
|||
crate::{
|
||||
bpf_loader, bpf_loader_deprecated, bpf_loader_upgradeable,
|
||||
clock::{Epoch, INITIAL_RENT_EPOCH},
|
||||
feature_set::{deprecate_executable_meta_update_in_bpf_loader, FeatureSet},
|
||||
lamports::LamportsError,
|
||||
loader_v4, native_loader,
|
||||
loader_v4,
|
||||
pubkey::Pubkey,
|
||||
},
|
||||
serde::{
|
||||
|
@ -40,9 +39,6 @@ pub struct Account {
|
|||
/// the program that owns this account. If executable, the program that loads this account.
|
||||
pub owner: Pubkey,
|
||||
/// this account's data contains a loaded program (and is now read-only)
|
||||
///
|
||||
/// When feature `deprecate_executable_meta_update_in_bpf_loader` is active,
|
||||
/// `executable` is deprecated, please use `fn is_executable(&account)` instead.
|
||||
pub executable: bool,
|
||||
/// the epoch at which this account will next owe rent
|
||||
pub rent_epoch: Epoch,
|
||||
|
@ -767,94 +763,6 @@ pub const PROGRAM_OWNERS: &[Pubkey] = &[
|
|||
loader_v4::id(),
|
||||
];
|
||||
|
||||
const LOADER_V4_STATUS_BYTE_OFFSET: usize = 40;
|
||||
|
||||
/// Create executable account meta data based on account's `owner`.
|
||||
///
|
||||
/// This function is only used for testing and an optimization during
|
||||
/// transaction loading.
|
||||
///
|
||||
/// When the program account is already present in the program cache, we don't
|
||||
/// need to load the full account data during transaction loading. Instead, all
|
||||
/// we need is a minimal executable account meta data, which is what this
|
||||
/// function returns.
|
||||
pub fn create_executable_meta(owner: &Pubkey) -> &[u8] {
|
||||
// For upgradable program account, only `UpgradeableLoaderState::Program`
|
||||
// variant (i.e. discriminant = 2) should *executable*, which means the
|
||||
// discriminant for the enum at byte offset 0 in account data is 2.
|
||||
const EXECUTABLE_META_FOR_BPF_LOADER_UPGRADABLE: [u8; 1] = [2];
|
||||
|
||||
// For loader v4 program, when LoaderV4Status (byte_offset = 40 in account
|
||||
// data) is set, the program is executable.
|
||||
const fn get_executable_meta_for_loader_v4() -> [u8; 41] {
|
||||
let mut v = [0; LOADER_V4_STATUS_BYTE_OFFSET + 1];
|
||||
v[LOADER_V4_STATUS_BYTE_OFFSET] = 1;
|
||||
v
|
||||
}
|
||||
const EXECUTABLE_META_FOR_LOADER_V4: [u8; LOADER_V4_STATUS_BYTE_OFFSET + 1] =
|
||||
get_executable_meta_for_loader_v4();
|
||||
|
||||
// For other owners, simple returns a 1 byte array would make it executable.
|
||||
const DEFAULT_EXECUTABLE_META: [u8; 1] = [1];
|
||||
|
||||
if bpf_loader_upgradeable::check_id(owner) {
|
||||
&EXECUTABLE_META_FOR_BPF_LOADER_UPGRADABLE
|
||||
} else if loader_v4::check_id(owner) {
|
||||
&EXECUTABLE_META_FOR_LOADER_V4
|
||||
} else {
|
||||
&DEFAULT_EXECUTABLE_META
|
||||
}
|
||||
}
|
||||
|
||||
/// Return true if the account program is executable.
|
||||
pub fn is_executable(account: &impl ReadableAccount, feature_set: &FeatureSet) -> bool {
|
||||
if !feature_set.is_active(&deprecate_executable_meta_update_in_bpf_loader::id()) {
|
||||
account.executable()
|
||||
} else {
|
||||
// First, check if the account is empty. Empty accounts are not executable.
|
||||
if account.data().is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// bpf_loader/bpf_loader_deprecated still relies on `executable` on the
|
||||
// program account. When the program account is finalized, the loader will
|
||||
// mark `executable` flag on the account. We can't emulate `executable` for
|
||||
// these two loaders. However, when `deprecate_executable` is true, we
|
||||
// should have already disabled the deployment of bpf_loader and
|
||||
// bpf_loader_deprecated. Therefore, we can safely assume that all those
|
||||
// programs are `executable`.
|
||||
if bpf_loader::check_id(account.owner()) || bpf_loader_deprecated::check_id(account.owner())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if bpf_loader_upgradeable::check_id(account.owner()) {
|
||||
// For upgradable program account, only
|
||||
// `UpgradeableLoaderState::Program` variant (i.e. discriminant = 2) is
|
||||
// *executable*.
|
||||
return account.data()[0] == 2;
|
||||
}
|
||||
|
||||
if loader_v4::check_id(account.owner()) {
|
||||
// LoaderV4Status (byte_offset = 40)
|
||||
// return account.data()[LOADER_V4_STATUS_BYTE_OFFSET] != 0;
|
||||
return false; // TODO: return false for now
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// Return true if the account program is a builtin program.
|
||||
///
|
||||
/// This function also ensures that all valid builtin programs have non-empty
|
||||
/// program data. Typically, the program data contains only the "name" for the
|
||||
/// program. If, for some reason, the program account's data is empty, we should
|
||||
/// exclude such a program from `builtins`.
|
||||
pub fn is_builtin(account: &impl ReadableAccount) -> bool {
|
||||
native_loader::check_id(account.owner()) && !account.data().is_empty()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -756,10 +756,6 @@ pub mod disable_bpf_loader_instructions {
|
|||
solana_sdk::declare_id!("7WeS1vfPRgeeoXArLh7879YcB9mgE9ktjPDtajXeWfXn");
|
||||
}
|
||||
|
||||
pub mod deprecate_executable_meta_update_in_bpf_loader {
|
||||
solana_sdk::declare_id!("k6uR1J9VtKJnTukBV2Eo15BEy434MBg8bT6hHQgmU8v");
|
||||
}
|
||||
|
||||
pub mod enable_zk_proof_from_account {
|
||||
solana_sdk::declare_id!("zkiTNuzBKxrCLMKehzuQeKZyLtX2yvFcEKMML8nExU8");
|
||||
}
|
||||
|
@ -967,7 +963,6 @@ lazy_static! {
|
|||
(index_erasure_conflict_duplicate_proofs::id(), "generate duplicate proofs for index and erasure conflicts #34360"),
|
||||
(merkle_conflict_duplicate_proofs::id(), "generate duplicate proofs for merkle root conflicts #34270"),
|
||||
(disable_bpf_loader_instructions::id(), "disable bpf loader management instructions #34194"),
|
||||
(deprecate_executable_meta_update_in_bpf_loader::id(), "deprecate executable meta flag update in bpf loader #34194"),
|
||||
(enable_zk_proof_from_account::id(), "Enable zk token proof program to read proof from accounts instead of instruction data #34750"),
|
||||
(curve25519_restrict_msm_length::id(), "restrict curve25519 multiscalar multiplication vector lengths #34763"),
|
||||
(cost_model_requested_write_lock_cost::id(), "cost model uses number of requested write locks #34819"),
|
||||
|
|
|
@ -17,8 +17,7 @@ use {
|
|||
};
|
||||
use {
|
||||
crate::{
|
||||
account::{is_builtin, is_executable, AccountSharedData, ReadableAccount},
|
||||
feature_set::FeatureSet,
|
||||
account::{AccountSharedData, ReadableAccount},
|
||||
instruction::InstructionError,
|
||||
pubkey::Pubkey,
|
||||
},
|
||||
|
@ -740,11 +739,7 @@ impl<'a> BorrowedAccount<'a> {
|
|||
|
||||
/// Assignes the owner of this account (transaction wide)
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
pub fn set_owner(
|
||||
&mut self,
|
||||
pubkey: &[u8],
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
pub fn set_owner(&mut self, pubkey: &[u8]) -> Result<(), InstructionError> {
|
||||
// Only the owner can assign a new owner
|
||||
if !self.is_owned_by_current_program() {
|
||||
return Err(InstructionError::ModifiedProgramId);
|
||||
|
@ -754,7 +749,7 @@ impl<'a> BorrowedAccount<'a> {
|
|||
return Err(InstructionError::ModifiedProgramId);
|
||||
}
|
||||
// and only if the account is not executable
|
||||
if self.is_executable(feature_set) {
|
||||
if self.is_executable() {
|
||||
return Err(InstructionError::ModifiedProgramId);
|
||||
}
|
||||
// and only if the data is zero-initialized or empty
|
||||
|
@ -778,11 +773,7 @@ impl<'a> BorrowedAccount<'a> {
|
|||
|
||||
/// Overwrites the number of lamports of this account (transaction wide)
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
pub fn set_lamports(
|
||||
&mut self,
|
||||
lamports: u64,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
pub fn set_lamports(&mut self, lamports: u64) -> Result<(), InstructionError> {
|
||||
// An account not owned by the program cannot have its balance decrease
|
||||
if !self.is_owned_by_current_program() && lamports < self.get_lamports() {
|
||||
return Err(InstructionError::ExternalAccountLamportSpend);
|
||||
|
@ -792,7 +783,7 @@ impl<'a> BorrowedAccount<'a> {
|
|||
return Err(InstructionError::ReadonlyLamportChange);
|
||||
}
|
||||
// The balance of executable accounts may not change
|
||||
if self.is_executable(feature_set) {
|
||||
if self.is_executable() {
|
||||
return Err(InstructionError::ExecutableLamportChange);
|
||||
}
|
||||
// don't touch the account if the lamports do not change
|
||||
|
@ -806,31 +797,21 @@ impl<'a> BorrowedAccount<'a> {
|
|||
|
||||
/// Adds lamports to this account (transaction wide)
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
pub fn checked_add_lamports(
|
||||
&mut self,
|
||||
lamports: u64,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
pub fn checked_add_lamports(&mut self, lamports: u64) -> Result<(), InstructionError> {
|
||||
self.set_lamports(
|
||||
self.get_lamports()
|
||||
.checked_add(lamports)
|
||||
.ok_or(InstructionError::ArithmeticOverflow)?,
|
||||
feature_set,
|
||||
)
|
||||
}
|
||||
|
||||
/// Subtracts lamports from this account (transaction wide)
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
pub fn checked_sub_lamports(
|
||||
&mut self,
|
||||
lamports: u64,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
pub fn checked_sub_lamports(&mut self, lamports: u64) -> Result<(), InstructionError> {
|
||||
self.set_lamports(
|
||||
self.get_lamports()
|
||||
.checked_sub(lamports)
|
||||
.ok_or(InstructionError::ArithmeticOverflow)?,
|
||||
feature_set,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -842,11 +823,8 @@ impl<'a> BorrowedAccount<'a> {
|
|||
|
||||
/// Returns a writable slice of the account data (transaction wide)
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
pub fn get_data_mut(
|
||||
&mut self,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<&mut [u8], InstructionError> {
|
||||
self.can_data_be_changed(feature_set)?;
|
||||
pub fn get_data_mut(&mut self) -> Result<&mut [u8], InstructionError> {
|
||||
self.can_data_be_changed()?;
|
||||
self.touch()?;
|
||||
self.make_data_mut();
|
||||
Ok(self.account.data_as_mut_slice())
|
||||
|
@ -871,13 +849,9 @@ impl<'a> BorrowedAccount<'a> {
|
|||
not(target_os = "solana"),
|
||||
any(test, feature = "dev-context-only-utils")
|
||||
))]
|
||||
pub fn set_data(
|
||||
&mut self,
|
||||
data: Vec<u8>,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
pub fn set_data(&mut self, data: Vec<u8>) -> Result<(), InstructionError> {
|
||||
self.can_data_be_resized(data.len())?;
|
||||
self.can_data_be_changed(feature_set)?;
|
||||
self.can_data_be_changed()?;
|
||||
self.touch()?;
|
||||
|
||||
self.update_accounts_resize_delta(data.len())?;
|
||||
|
@ -890,18 +864,14 @@ impl<'a> BorrowedAccount<'a> {
|
|||
/// Call this when you have a slice of data you do not own and want to
|
||||
/// replace the account data with it.
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
pub fn set_data_from_slice(
|
||||
&mut self,
|
||||
data: &[u8],
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
pub fn set_data_from_slice(&mut self, data: &[u8]) -> Result<(), InstructionError> {
|
||||
self.can_data_be_resized(data.len())?;
|
||||
self.can_data_be_changed(feature_set)?;
|
||||
self.can_data_be_changed()?;
|
||||
self.touch()?;
|
||||
self.update_accounts_resize_delta(data.len())?;
|
||||
// Calling make_data_mut() here guarantees that set_data_from_slice()
|
||||
// copies in places, extending the account capacity if necessary but
|
||||
// never reducing it. This is required as the account might be directly
|
||||
// never reducing it. This is required as the account migh be directly
|
||||
// mapped into a MemoryRegion, and therefore reducing capacity would
|
||||
// leave a hole in the vm address space. After CPI or upon program
|
||||
// termination, the runtime will zero the extra capacity.
|
||||
|
@ -915,13 +885,9 @@ impl<'a> BorrowedAccount<'a> {
|
|||
///
|
||||
/// Fills it with zeros at the end if is extended or truncates at the end otherwise.
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
pub fn set_data_length(
|
||||
&mut self,
|
||||
new_length: usize,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
pub fn set_data_length(&mut self, new_length: usize) -> Result<(), InstructionError> {
|
||||
self.can_data_be_resized(new_length)?;
|
||||
self.can_data_be_changed(feature_set)?;
|
||||
self.can_data_be_changed()?;
|
||||
// don't touch the account if the length does not change
|
||||
if self.get_data().len() == new_length {
|
||||
return Ok(());
|
||||
|
@ -934,14 +900,10 @@ impl<'a> BorrowedAccount<'a> {
|
|||
|
||||
/// Appends all elements in a slice to the account
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
pub fn extend_from_slice(
|
||||
&mut self,
|
||||
data: &[u8],
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
pub fn extend_from_slice(&mut self, data: &[u8]) -> Result<(), InstructionError> {
|
||||
let new_len = self.get_data().len().saturating_add(data.len());
|
||||
self.can_data_be_resized(new_len)?;
|
||||
self.can_data_be_changed(feature_set)?;
|
||||
self.can_data_be_changed()?;
|
||||
|
||||
if data.is_empty() {
|
||||
return Ok(());
|
||||
|
@ -995,7 +957,7 @@ impl<'a> BorrowedAccount<'a> {
|
|||
// about to write into it. Make the account mutable by copying it in a
|
||||
// buffer with MAX_PERMITTED_DATA_INCREASE capacity so that if the
|
||||
// transaction reallocs, we don't have to copy the whole account data a
|
||||
// second time to fulfill the realloc.
|
||||
// second time to fullfill the realloc.
|
||||
//
|
||||
// NOTE: The account memory region CoW code in bpf_loader::create_vm() implements the same
|
||||
// logic and must be kept in sync.
|
||||
|
@ -1014,12 +976,8 @@ impl<'a> BorrowedAccount<'a> {
|
|||
|
||||
/// Serializes a state into the account data
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
pub fn set_state<T: serde::Serialize>(
|
||||
&mut self,
|
||||
state: &T,
|
||||
feature_set: &FeatureSet,
|
||||
) -> Result<(), InstructionError> {
|
||||
let data = self.get_data_mut(feature_set)?;
|
||||
pub fn set_state<T: serde::Serialize>(&mut self, state: &T) -> Result<(), InstructionError> {
|
||||
let data = self.get_data_mut()?;
|
||||
let serialized_size =
|
||||
bincode::serialized_size(state).map_err(|_| InstructionError::GenericError)?;
|
||||
if serialized_size > data.len() as u64 {
|
||||
|
@ -1040,8 +998,8 @@ impl<'a> BorrowedAccount<'a> {
|
|||
|
||||
/// Returns whether this account is executable (transaction wide)
|
||||
#[inline]
|
||||
pub fn is_executable(&self, feature_set: &FeatureSet) -> bool {
|
||||
is_builtin(&*self.account) || is_executable(&*self.account, feature_set)
|
||||
pub fn is_executable(&self) -> bool {
|
||||
self.account.executable()
|
||||
}
|
||||
|
||||
/// Configures whether this account is executable (transaction wide)
|
||||
|
@ -1064,11 +1022,11 @@ impl<'a> BorrowedAccount<'a> {
|
|||
return Err(InstructionError::ExecutableModified);
|
||||
}
|
||||
// one can not clear the executable flag
|
||||
if self.account.executable() && !is_executable {
|
||||
if self.is_executable() && !is_executable {
|
||||
return Err(InstructionError::ExecutableModified);
|
||||
}
|
||||
// don't touch the account if the executable flag does not change
|
||||
if self.account.executable() == is_executable {
|
||||
if self.is_executable() == is_executable {
|
||||
return Ok(());
|
||||
}
|
||||
self.touch()?;
|
||||
|
@ -1119,9 +1077,9 @@ impl<'a> BorrowedAccount<'a> {
|
|||
|
||||
/// Returns an error if the account data can not be mutated by the current program
|
||||
#[cfg(not(target_os = "solana"))]
|
||||
pub fn can_data_be_changed(&self, feature_set: &FeatureSet) -> Result<(), InstructionError> {
|
||||
pub fn can_data_be_changed(&self) -> Result<(), InstructionError> {
|
||||
// Only non-executable accounts data can be changed
|
||||
if self.is_executable(feature_set) {
|
||||
if self.is_executable() {
|
||||
return Err(InstructionError::ExecutableDataModified);
|
||||
}
|
||||
// and only if the account is writable
|
||||
|
|
|
@ -11,10 +11,7 @@ use {
|
|||
loaded_programs::LoadedProgramsForTxBatch,
|
||||
},
|
||||
solana_sdk::{
|
||||
account::{
|
||||
create_executable_meta, is_builtin, is_executable, Account, AccountSharedData,
|
||||
ReadableAccount, WritableAccount,
|
||||
},
|
||||
account::{Account, AccountSharedData, ReadableAccount, WritableAccount},
|
||||
feature_set::{
|
||||
self, include_loaded_accounts_data_size_in_fee_calculation,
|
||||
remove_rounding_in_fee_calculation,
|
||||
|
@ -336,7 +333,7 @@ fn load_transaction_accounts<CB: TransactionProcessingCallback>(
|
|||
return Err(TransactionError::ProgramAccountNotFound);
|
||||
}
|
||||
|
||||
if !(is_builtin(program_account) || is_executable(program_account, &feature_set)) {
|
||||
if !program_account.executable() {
|
||||
error_counters.invalid_program_for_execution += 1;
|
||||
return Err(TransactionError::InvalidProgramForExecution);
|
||||
}
|
||||
|
@ -356,8 +353,7 @@ fn load_transaction_accounts<CB: TransactionProcessingCallback>(
|
|||
let owner_index = accounts.len();
|
||||
if let Some(owner_account) = callbacks.get_account_shared_data(owner_id) {
|
||||
if !native_loader::check_id(owner_account.owner())
|
||||
|| !(is_builtin(&owner_account)
|
||||
|| is_executable(&owner_account, &feature_set))
|
||||
|| !owner_account.executable()
|
||||
{
|
||||
error_counters.invalid_program_for_execution += 1;
|
||||
return Err(TransactionError::InvalidProgramForExecution);
|
||||
|
@ -423,7 +419,6 @@ fn account_shared_data_from_program(
|
|||
.ok_or(TransactionError::AccountNotFound)?;
|
||||
program_account.set_owner(**program_owner);
|
||||
program_account.set_executable(true);
|
||||
program_account.set_data_from_slice(create_executable_meta(program_owner));
|
||||
Ok(program_account)
|
||||
}
|
||||
|
||||
|
@ -887,7 +882,7 @@ mod tests {
|
|||
|
||||
let mut account = AccountSharedData::new(40, 1, &Pubkey::default());
|
||||
account.set_owner(bpf_loader_upgradeable::id());
|
||||
account.set_data(create_executable_meta(account.owner()).to_vec());
|
||||
account.set_executable(true);
|
||||
accounts.push((key1, account));
|
||||
|
||||
let instructions = vec![CompiledInstruction::new(1, &(), vec![0])];
|
||||
|
@ -967,7 +962,6 @@ mod tests {
|
|||
account.set_executable(true);
|
||||
account.set_rent_epoch(1);
|
||||
account.set_owner(key1);
|
||||
account.set_data(create_executable_meta(account.owner()).to_vec());
|
||||
accounts.push((key2, account));
|
||||
|
||||
let instructions = vec![
|
||||
|
@ -1428,7 +1422,6 @@ mod tests {
|
|||
let mut expected = AccountSharedData::default();
|
||||
expected.set_owner(other_key);
|
||||
expected.set_executable(true);
|
||||
expected.set_data_from_slice(create_executable_meta(&other_key));
|
||||
|
||||
assert_eq!(result.unwrap(), expected);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue