Cleanup: InvokeContext accessors (#21574)
* Removes blockhash accessors from InvokeContext. * Removes lamports_per_signature accessors from InvokeContext. * Removes return_data accessors from InvokeContext. * Removes feature_set accessor from InvokeContext. * Removes instruction_recorders and instruction_index accessors from InvokeContext. * Moves get_sysvars() into InvokeContext. * Removes compute_meter parameter from InvokeContext::new(). * Removes InvokeContext::new_mock_with_sysvars_and_features(). * Removes InvokeContext::update_timing().
This commit is contained in:
parent
dab0e8fdc7
commit
a9d5ef2055
|
@ -131,24 +131,23 @@ impl<'a> StackFrame<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct InvokeContext<'a> {
|
pub struct InvokeContext<'a> {
|
||||||
instruction_index: usize,
|
|
||||||
invoke_stack: Vec<StackFrame<'a>>,
|
invoke_stack: Vec<StackFrame<'a>>,
|
||||||
rent: Rent,
|
rent: Rent,
|
||||||
pre_accounts: Vec<PreAccount>,
|
pre_accounts: Vec<PreAccount>,
|
||||||
accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)],
|
accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)],
|
||||||
builtin_programs: &'a [BuiltinProgram],
|
builtin_programs: &'a [BuiltinProgram],
|
||||||
sysvars: &'a [(Pubkey, Vec<u8>)],
|
pub sysvars: &'a [(Pubkey, Vec<u8>)],
|
||||||
log_collector: Option<Rc<RefCell<LogCollector>>>,
|
log_collector: Option<Rc<RefCell<LogCollector>>>,
|
||||||
compute_budget: ComputeBudget,
|
compute_budget: ComputeBudget,
|
||||||
current_compute_budget: ComputeBudget,
|
current_compute_budget: ComputeBudget,
|
||||||
compute_meter: Rc<RefCell<ComputeMeter>>,
|
compute_meter: Rc<RefCell<ComputeMeter>>,
|
||||||
executors: Rc<RefCell<Executors>>,
|
executors: Rc<RefCell<Executors>>,
|
||||||
instruction_recorders: Option<&'a [InstructionRecorder]>,
|
pub instruction_recorder: Option<&'a InstructionRecorder>,
|
||||||
feature_set: Arc<FeatureSet>,
|
pub feature_set: Arc<FeatureSet>,
|
||||||
pub timings: ExecuteDetailsTimings,
|
pub timings: ExecuteDetailsTimings,
|
||||||
blockhash: Hash,
|
pub blockhash: Hash,
|
||||||
lamports_per_signature: u64,
|
pub lamports_per_signature: u64,
|
||||||
return_data: (Pubkey, Vec<u8>),
|
pub return_data: (Pubkey, Vec<u8>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> InvokeContext<'a> {
|
impl<'a> InvokeContext<'a> {
|
||||||
|
@ -160,15 +159,12 @@ impl<'a> InvokeContext<'a> {
|
||||||
sysvars: &'a [(Pubkey, Vec<u8>)],
|
sysvars: &'a [(Pubkey, Vec<u8>)],
|
||||||
log_collector: Option<Rc<RefCell<LogCollector>>>,
|
log_collector: Option<Rc<RefCell<LogCollector>>>,
|
||||||
compute_budget: ComputeBudget,
|
compute_budget: ComputeBudget,
|
||||||
compute_meter: Rc<RefCell<ComputeMeter>>,
|
|
||||||
executors: Rc<RefCell<Executors>>,
|
executors: Rc<RefCell<Executors>>,
|
||||||
instruction_recorders: Option<&'a [InstructionRecorder]>,
|
|
||||||
feature_set: Arc<FeatureSet>,
|
feature_set: Arc<FeatureSet>,
|
||||||
blockhash: Hash,
|
blockhash: Hash,
|
||||||
lamports_per_signature: u64,
|
lamports_per_signature: u64,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
instruction_index: 0,
|
|
||||||
invoke_stack: Vec::with_capacity(compute_budget.max_invoke_depth),
|
invoke_stack: Vec::with_capacity(compute_budget.max_invoke_depth),
|
||||||
rent,
|
rent,
|
||||||
pre_accounts: Vec::new(),
|
pre_accounts: Vec::new(),
|
||||||
|
@ -178,9 +174,9 @@ impl<'a> InvokeContext<'a> {
|
||||||
log_collector,
|
log_collector,
|
||||||
current_compute_budget: compute_budget,
|
current_compute_budget: compute_budget,
|
||||||
compute_budget,
|
compute_budget,
|
||||||
compute_meter,
|
compute_meter: ComputeMeter::new_ref(compute_budget.max_units),
|
||||||
executors,
|
executors,
|
||||||
instruction_recorders,
|
instruction_recorder: None,
|
||||||
feature_set,
|
feature_set,
|
||||||
timings: ExecuteDetailsTimings::default(),
|
timings: ExecuteDetailsTimings::default(),
|
||||||
blockhash,
|
blockhash,
|
||||||
|
@ -189,40 +185,24 @@ impl<'a> InvokeContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_mock_with_sysvars_and_features(
|
pub fn new_mock(
|
||||||
accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)],
|
accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)],
|
||||||
builtin_programs: &'a [BuiltinProgram],
|
builtin_programs: &'a [BuiltinProgram],
|
||||||
sysvars: &'a [(Pubkey, Vec<u8>)],
|
|
||||||
feature_set: Arc<FeatureSet>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new(
|
Self::new(
|
||||||
Rent::default(),
|
Rent::default(),
|
||||||
accounts,
|
accounts,
|
||||||
builtin_programs,
|
builtin_programs,
|
||||||
sysvars,
|
&[],
|
||||||
Some(LogCollector::new_ref()),
|
Some(LogCollector::new_ref()),
|
||||||
ComputeBudget::default(),
|
ComputeBudget::default(),
|
||||||
ComputeMeter::new_ref(std::i64::MAX as u64),
|
|
||||||
Rc::new(RefCell::new(Executors::default())),
|
Rc::new(RefCell::new(Executors::default())),
|
||||||
None,
|
Arc::new(FeatureSet::all_enabled()),
|
||||||
feature_set,
|
|
||||||
Hash::default(),
|
Hash::default(),
|
||||||
0,
|
0,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_mock(
|
|
||||||
accounts: &'a [(Pubkey, Rc<RefCell<AccountSharedData>>)],
|
|
||||||
builtin_programs: &'a [BuiltinProgram],
|
|
||||||
) -> Self {
|
|
||||||
Self::new_mock_with_sysvars_and_features(
|
|
||||||
accounts,
|
|
||||||
builtin_programs,
|
|
||||||
&[],
|
|
||||||
Arc::new(FeatureSet::all_enabled()),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Push a stack frame onto the invocation stack
|
/// Push a stack frame onto the invocation stack
|
||||||
pub fn push(
|
pub fn push(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -240,15 +220,15 @@ impl<'a> InvokeContext<'a> {
|
||||||
.map(|index_of_program_id| &self.accounts[*index_of_program_id].0);
|
.map(|index_of_program_id| &self.accounts[*index_of_program_id].0);
|
||||||
if self.invoke_stack.is_empty() {
|
if self.invoke_stack.is_empty() {
|
||||||
let mut compute_budget = self.compute_budget;
|
let mut compute_budget = self.compute_budget;
|
||||||
if !self.is_feature_active(&tx_wide_compute_cap::id())
|
if !self.feature_set.is_active(&tx_wide_compute_cap::id())
|
||||||
&& self.is_feature_active(&neon_evm_compute_budget::id())
|
&& self.feature_set.is_active(&neon_evm_compute_budget::id())
|
||||||
&& program_id == Some(&crate::neon_evm_program::id())
|
&& program_id == Some(&crate::neon_evm_program::id())
|
||||||
{
|
{
|
||||||
// Bump the compute budget for neon_evm
|
// Bump the compute budget for neon_evm
|
||||||
compute_budget.max_units = compute_budget.max_units.max(500_000);
|
compute_budget.max_units = compute_budget.max_units.max(500_000);
|
||||||
}
|
}
|
||||||
if !self.is_feature_active(&requestable_heap_size::id())
|
if !self.feature_set.is_active(&requestable_heap_size::id())
|
||||||
&& self.is_feature_active(&neon_evm_compute_budget::id())
|
&& self.feature_set.is_active(&neon_evm_compute_budget::id())
|
||||||
&& program_id == Some(&crate::neon_evm_program::id())
|
&& program_id == Some(&crate::neon_evm_program::id())
|
||||||
{
|
{
|
||||||
// Bump the compute budget for neon_evm
|
// Bump the compute budget for neon_evm
|
||||||
|
@ -342,8 +322,10 @@ impl<'a> InvokeContext<'a> {
|
||||||
program_indices: &[usize],
|
program_indices: &[usize],
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let program_id = instruction.program_id(&message.account_keys);
|
let program_id = instruction.program_id(&message.account_keys);
|
||||||
let demote_program_write_locks = self.is_feature_active(&demote_program_write_locks::id());
|
let demote_program_write_locks = self
|
||||||
let do_support_realloc = self.is_feature_active(&do_support_realloc::id());
|
.feature_set
|
||||||
|
.is_active(&demote_program_write_locks::id());
|
||||||
|
let do_support_realloc = self.feature_set.is_active(&do_support_realloc::id());
|
||||||
|
|
||||||
// Verify all executable accounts have zero outstanding refs
|
// Verify all executable accounts have zero outstanding refs
|
||||||
for account_index in program_indices.iter() {
|
for account_index in program_indices.iter() {
|
||||||
|
@ -501,7 +483,9 @@ impl<'a> InvokeContext<'a> {
|
||||||
prev_account_sizes.push((account, account_length));
|
prev_account_sizes.push((account, account_length));
|
||||||
}
|
}
|
||||||
|
|
||||||
self.record_instruction(&instruction);
|
if let Some(instruction_recorder) = &self.instruction_recorder {
|
||||||
|
instruction_recorder.record_instruction(instruction);
|
||||||
|
}
|
||||||
self.process_cross_program_instruction(
|
self.process_cross_program_instruction(
|
||||||
&message,
|
&message,
|
||||||
&program_indices,
|
&program_indices,
|
||||||
|
@ -510,7 +494,7 @@ impl<'a> InvokeContext<'a> {
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Verify the called program has not misbehaved
|
// Verify the called program has not misbehaved
|
||||||
let do_support_realloc = self.is_feature_active(&do_support_realloc::id());
|
let do_support_realloc = self.feature_set.is_active(&do_support_realloc::id());
|
||||||
for (account, prev_size) in prev_account_sizes.iter() {
|
for (account, prev_size) in prev_account_sizes.iter() {
|
||||||
if !do_support_realloc && *prev_size != account.borrow().data().len() && *prev_size != 0
|
if !do_support_realloc && *prev_size != account.borrow().data().len() && *prev_size != 0
|
||||||
{
|
{
|
||||||
|
@ -657,12 +641,13 @@ impl<'a> InvokeContext<'a> {
|
||||||
// Verify the calling program hasn't misbehaved
|
// Verify the calling program hasn't misbehaved
|
||||||
self.verify_and_update(instruction, account_indices, caller_write_privileges)?;
|
self.verify_and_update(instruction, account_indices, caller_write_privileges)?;
|
||||||
|
|
||||||
self.set_return_data(Vec::new())?;
|
self.return_data = (*self.get_caller()?, Vec::new());
|
||||||
self.push(message, instruction, program_indices, Some(account_indices))?;
|
self.push(message, instruction, program_indices, Some(account_indices))?;
|
||||||
let result = self.process_instruction(&instruction.data).and_then(|_| {
|
let result = self.process_instruction(&instruction.data).and_then(|_| {
|
||||||
// Verify the called program has not misbehaved
|
// Verify the called program has not misbehaved
|
||||||
let demote_program_write_locks =
|
let demote_program_write_locks = self
|
||||||
self.is_feature_active(&demote_program_write_locks::id());
|
.feature_set
|
||||||
|
.is_active(&demote_program_write_locks::id());
|
||||||
let write_privileges: Vec<bool> = (0..message.account_keys.len())
|
let write_privileges: Vec<bool> = (0..message.account_keys.len())
|
||||||
.map(|i| message.is_writable(i, demote_program_write_locks))
|
.map(|i| message.is_writable(i, demote_program_write_locks))
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -692,7 +677,7 @@ impl<'a> InvokeContext<'a> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !self.is_feature_active(&remove_native_loader::id()) {
|
if !self.feature_set.is_active(&remove_native_loader::id()) {
|
||||||
let native_loader = NativeLoader::default();
|
let native_loader = NativeLoader::default();
|
||||||
// Call the program via the native loader
|
// Call the program via the native loader
|
||||||
return native_loader.process_instruction(0, instruction_data, self);
|
return native_loader.process_instruction(0, instruction_data, self);
|
||||||
|
@ -733,7 +718,7 @@ impl<'a> InvokeContext<'a> {
|
||||||
note = "To be removed together with remove_native_loader"
|
note = "To be removed together with remove_native_loader"
|
||||||
)]
|
)]
|
||||||
pub fn remove_first_keyed_account(&mut self) -> Result<(), InstructionError> {
|
pub fn remove_first_keyed_account(&mut self) -> Result<(), InstructionError> {
|
||||||
if !self.is_feature_active(&remove_native_loader::id()) {
|
if !self.feature_set.is_active(&remove_native_loader::id()) {
|
||||||
let stack_frame = &mut self
|
let stack_frame = &mut self
|
||||||
.invoke_stack
|
.invoke_stack
|
||||||
.last_mut()
|
.last_mut()
|
||||||
|
@ -786,23 +771,6 @@ impl<'a> InvokeContext<'a> {
|
||||||
self.executors.borrow().get(pubkey)
|
self.executors.borrow().get(pubkey)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set which instruction in the message is currently being recorded
|
|
||||||
pub fn set_instruction_index(&mut self, instruction_index: usize) {
|
|
||||||
self.instruction_index = instruction_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Record invoked instruction
|
|
||||||
pub fn record_instruction(&self, instruction: &Instruction) {
|
|
||||||
if let Some(instruction_recorders) = &self.instruction_recorders {
|
|
||||||
instruction_recorders[self.instruction_index].record_instruction(instruction.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the bank's active feature set
|
|
||||||
pub fn is_feature_active(&self, feature_id: &Pubkey) -> bool {
|
|
||||||
self.feature_set.is_active(feature_id)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Find an account_index and account by its key
|
/// Find an account_index and account by its key
|
||||||
pub fn get_account(&self, pubkey: &Pubkey) -> Option<(usize, Rc<RefCell<AccountSharedData>>)> {
|
pub fn get_account(&self, pubkey: &Pubkey) -> Option<(usize, Rc<RefCell<AccountSharedData>>)> {
|
||||||
for (index, (key, account)) in self.accounts.iter().enumerate().rev() {
|
for (index, (key, account)) in self.accounts.iter().enumerate().rev() {
|
||||||
|
@ -813,70 +781,14 @@ impl<'a> InvokeContext<'a> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update timing
|
|
||||||
pub fn update_timing(
|
|
||||||
&mut self,
|
|
||||||
serialize_us: u64,
|
|
||||||
create_vm_us: u64,
|
|
||||||
execute_us: u64,
|
|
||||||
deserialize_us: u64,
|
|
||||||
) {
|
|
||||||
self.timings.serialize_us = self.timings.serialize_us.saturating_add(serialize_us);
|
|
||||||
self.timings.create_vm_us = self.timings.create_vm_us.saturating_add(create_vm_us);
|
|
||||||
self.timings.execute_us = self.timings.execute_us.saturating_add(execute_us);
|
|
||||||
self.timings.deserialize_us = self.timings.deserialize_us.saturating_add(deserialize_us);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get cached sysvars
|
|
||||||
pub fn get_sysvars(&self) -> &[(Pubkey, Vec<u8>)] {
|
|
||||||
self.sysvars
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get this invocation's compute budget
|
/// Get this invocation's compute budget
|
||||||
pub fn get_compute_budget(&self) -> &ComputeBudget {
|
pub fn get_compute_budget(&self) -> &ComputeBudget {
|
||||||
&self.current_compute_budget
|
&self.current_compute_budget
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set this invocation's blockhash
|
/// Get the value of a sysvar by its id
|
||||||
pub fn set_blockhash(&mut self, hash: Hash) {
|
pub fn get_sysvar<T: Sysvar>(&self, id: &Pubkey) -> Result<T, InstructionError> {
|
||||||
self.blockhash = hash;
|
self.sysvars
|
||||||
}
|
|
||||||
|
|
||||||
/// Get this invocation's blockhash
|
|
||||||
pub fn get_blockhash(&self) -> &Hash {
|
|
||||||
&self.blockhash
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set this invocation's lamports_per_signature value
|
|
||||||
pub fn set_lamports_per_signature(&mut self, lamports_per_signature: u64) {
|
|
||||||
self.lamports_per_signature = lamports_per_signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get this invocation's lamports_per_signature value
|
|
||||||
pub fn get_lamports_per_signature(&self) -> u64 {
|
|
||||||
self.lamports_per_signature
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Set the return data
|
|
||||||
pub fn set_return_data(&mut self, data: Vec<u8>) -> Result<(), InstructionError> {
|
|
||||||
self.return_data = (*self.get_caller()?, data);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the return data
|
|
||||||
pub fn get_return_data(&self) -> (Pubkey, &[u8]) {
|
|
||||||
(self.return_data.0, &self.return_data.1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// This method which has a generic parameter is outside of the InvokeContext,
|
|
||||||
// because the InvokeContext is a dyn Trait.
|
|
||||||
pub fn get_sysvar<T: Sysvar>(
|
|
||||||
invoke_context: &InvokeContext,
|
|
||||||
id: &Pubkey,
|
|
||||||
) -> Result<T, InstructionError> {
|
|
||||||
invoke_context
|
|
||||||
.get_sysvars()
|
|
||||||
.iter()
|
.iter()
|
||||||
.find_map(|(key, data)| {
|
.find_map(|(key, data)| {
|
||||||
if id == key {
|
if id == key {
|
||||||
|
@ -886,10 +798,11 @@ pub fn get_sysvar<T: Sysvar>(
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
ic_msg!(invoke_context, "Unable to get sysvar {}", id);
|
ic_msg!(self, "Unable to get sysvar {}", id);
|
||||||
InstructionError::UnsupportedSysvar
|
InstructionError::UnsupportedSysvar
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct MockInvokeContextPreparation {
|
pub struct MockInvokeContextPreparation {
|
||||||
pub accounts: Vec<(Pubkey, Rc<RefCell<AccountSharedData>>)>,
|
pub accounts: Vec<(Pubkey, Rc<RefCell<AccountSharedData>>)>,
|
||||||
|
@ -1300,8 +1213,9 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
// not owned account modified by the caller (before the invoke)
|
// not owned account modified by the caller (before the invoke)
|
||||||
let demote_program_write_locks =
|
let demote_program_write_locks = invoke_context
|
||||||
invoke_context.is_feature_active(&demote_program_write_locks::id());
|
.feature_set
|
||||||
|
.is_active(&demote_program_write_locks::id());
|
||||||
let caller_write_privileges = message
|
let caller_write_privileges = message
|
||||||
.account_keys
|
.account_keys
|
||||||
.iter()
|
.iter()
|
||||||
|
@ -1509,12 +1423,8 @@ mod tests {
|
||||||
let mut feature_set = FeatureSet::all_enabled();
|
let mut feature_set = FeatureSet::all_enabled();
|
||||||
feature_set.deactivate(&tx_wide_compute_cap::id());
|
feature_set.deactivate(&tx_wide_compute_cap::id());
|
||||||
feature_set.deactivate(&requestable_heap_size::id());
|
feature_set.deactivate(&requestable_heap_size::id());
|
||||||
let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features(
|
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
|
||||||
&accounts,
|
invoke_context.feature_set = Arc::new(feature_set);
|
||||||
&[],
|
|
||||||
&[],
|
|
||||||
Arc::new(feature_set),
|
|
||||||
);
|
|
||||||
|
|
||||||
invoke_context
|
invoke_context
|
||||||
.push(&noop_message, &noop_message.instructions[0], &[0], None)
|
.push(&noop_message, &noop_message.instructions[0], &[0], None)
|
||||||
|
|
|
@ -214,7 +214,7 @@ fn get_sysvar<T: Default + Sysvar + Sized + serde::de::DeserializeOwned>(
|
||||||
panic!("Exceeded compute budget");
|
panic!("Exceeded compute budget");
|
||||||
}
|
}
|
||||||
|
|
||||||
match solana_program_runtime::invoke_context::get_sysvar::<T>(invoke_context, id) {
|
match invoke_context.get_sysvar::<T>(id) {
|
||||||
Ok(sysvar_data) => unsafe {
|
Ok(sysvar_data) => unsafe {
|
||||||
*(var_addr as *mut _ as *mut T) = sysvar_data;
|
*(var_addr as *mut _ as *mut T) = sysvar_data;
|
||||||
SUCCESS
|
SUCCESS
|
||||||
|
@ -248,8 +248,9 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
|
||||||
let message = Message::new(&[instruction.clone()], None);
|
let message = Message::new(&[instruction.clone()], None);
|
||||||
let program_id_index = message.instructions[0].program_id_index as usize;
|
let program_id_index = message.instructions[0].program_id_index as usize;
|
||||||
let program_id = message.account_keys[program_id_index];
|
let program_id = message.account_keys[program_id_index];
|
||||||
let demote_program_write_locks =
|
let demote_program_write_locks = invoke_context
|
||||||
invoke_context.is_feature_active(&demote_program_write_locks::id());
|
.feature_set
|
||||||
|
.is_active(&demote_program_write_locks::id());
|
||||||
// TODO don't have the caller's keyed_accounts so can't validate writer or signer escalation or deescalation yet
|
// TODO don't have the caller's keyed_accounts so can't validate writer or signer escalation or deescalation yet
|
||||||
let caller_privileges = message
|
let caller_privileges = message
|
||||||
.account_keys
|
.account_keys
|
||||||
|
@ -317,7 +318,9 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
invoke_context.record_instruction(instruction);
|
if let Some(instruction_recorder) = &invoke_context.instruction_recorder {
|
||||||
|
instruction_recorder.record_instruction(instruction.clone());
|
||||||
|
}
|
||||||
|
|
||||||
invoke_context
|
invoke_context
|
||||||
.process_cross_program_instruction(
|
.process_cross_program_instruction(
|
||||||
|
|
|
@ -99,6 +99,10 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
||||||
let elf = load_elf("bench_alu").unwrap();
|
let elf = load_elf("bench_alu").unwrap();
|
||||||
let loader_id = bpf_loader::id();
|
let loader_id = bpf_loader::id();
|
||||||
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
||||||
|
invoke_context
|
||||||
|
.get_compute_meter()
|
||||||
|
.borrow_mut()
|
||||||
|
.mock_set_remaining(std::i64::MAX as u64);
|
||||||
let mut executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
let mut executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
||||||
&elf,
|
&elf,
|
||||||
None,
|
None,
|
||||||
|
@ -109,13 +113,7 @@ fn bench_program_alu(bencher: &mut Bencher) {
|
||||||
executable.jit_compile().unwrap();
|
executable.jit_compile().unwrap();
|
||||||
let compute_meter = invoke_context.get_compute_meter();
|
let compute_meter = invoke_context.get_compute_meter();
|
||||||
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
let mut instruction_meter = ThisInstructionMeter { compute_meter };
|
||||||
let mut vm = create_vm(
|
let mut vm = create_vm(&executable, &mut inner_iter, invoke_context, &[]).unwrap();
|
||||||
&executable,
|
|
||||||
&mut inner_iter,
|
|
||||||
invoke_context,
|
|
||||||
&[],
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
println!("Interpreted:");
|
println!("Interpreted:");
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -205,7 +203,10 @@ fn bench_create_vm(bencher: &mut Bencher) {
|
||||||
let loader_id = bpf_loader::id();
|
let loader_id = bpf_loader::id();
|
||||||
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
||||||
const BUDGET: u64 = 200_000;
|
const BUDGET: u64 = 200_000;
|
||||||
invoke_context.get_compute_meter().borrow_mut().mock_set_remaining(BUDGET);
|
invoke_context
|
||||||
|
.get_compute_meter()
|
||||||
|
.borrow_mut()
|
||||||
|
.mock_set_remaining(BUDGET);
|
||||||
|
|
||||||
// Serialize account data
|
// Serialize account data
|
||||||
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
||||||
|
@ -243,7 +244,10 @@ fn bench_instruction_count_tuner(_bencher: &mut Bencher) {
|
||||||
let loader_id = bpf_loader::id();
|
let loader_id = bpf_loader::id();
|
||||||
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
with_mock_invoke_context(loader_id, 10000001, |invoke_context| {
|
||||||
const BUDGET: u64 = 200_000;
|
const BUDGET: u64 = 200_000;
|
||||||
invoke_context.get_compute_meter().borrow_mut().mock_set_remaining(BUDGET);
|
invoke_context
|
||||||
|
.get_compute_meter()
|
||||||
|
.borrow_mut()
|
||||||
|
.mock_set_remaining(BUDGET);
|
||||||
|
|
||||||
// Serialize account data
|
// Serialize account data
|
||||||
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
let keyed_accounts = invoke_context.get_keyed_accounts().unwrap();
|
||||||
|
|
|
@ -223,7 +223,7 @@ fn run_program(name: &str) -> u64 {
|
||||||
let mut instruction_count = 0;
|
let mut instruction_count = 0;
|
||||||
let mut tracer = None;
|
let mut tracer = None;
|
||||||
for i in 0..2 {
|
for i in 0..2 {
|
||||||
invoke_context.set_return_data(Vec::new()).unwrap();
|
invoke_context.return_data = (*invoke_context.get_caller().unwrap(), Vec::new());
|
||||||
let mut parameter_bytes = parameter_bytes.clone();
|
let mut parameter_bytes = parameter_bytes.clone();
|
||||||
{
|
{
|
||||||
let mut vm = create_vm(
|
let mut vm = create_vm(
|
||||||
|
|
|
@ -91,9 +91,12 @@ pub fn create_executor(
|
||||||
stack_frame_size: compute_budget.stack_frame_size,
|
stack_frame_size: compute_budget.stack_frame_size,
|
||||||
enable_instruction_tracing: log_enabled!(Trace),
|
enable_instruction_tracing: log_enabled!(Trace),
|
||||||
reject_unresolved_syscalls: reject_unresolved_syscalls
|
reject_unresolved_syscalls: reject_unresolved_syscalls
|
||||||
&& invoke_context.is_feature_active(&reject_deployment_of_unresolved_syscalls::id()),
|
&& invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&reject_deployment_of_unresolved_syscalls::id()),
|
||||||
verify_mul64_imm_nonzero: !invoke_context
|
verify_mul64_imm_nonzero: !invoke_context
|
||||||
.is_feature_active(&stop_verify_mul64_imm_nonzero::id()), // TODO: Feature gate and then remove me
|
.feature_set
|
||||||
|
.is_active(&stop_verify_mul64_imm_nonzero::id()), // TODO: Feature gate and then remove me
|
||||||
..Config::default()
|
..Config::default()
|
||||||
};
|
};
|
||||||
let mut executable = {
|
let mut executable = {
|
||||||
|
@ -158,7 +161,10 @@ pub fn create_vm<'a, 'b>(
|
||||||
) -> Result<EbpfVm<'a, BpfError, ThisInstructionMeter>, EbpfError<BpfError>> {
|
) -> Result<EbpfVm<'a, BpfError, ThisInstructionMeter>, EbpfError<BpfError>> {
|
||||||
let compute_budget = invoke_context.get_compute_budget();
|
let compute_budget = invoke_context.get_compute_budget();
|
||||||
let heap_size = compute_budget.heap_size.unwrap_or(HEAP_LENGTH);
|
let heap_size = compute_budget.heap_size.unwrap_or(HEAP_LENGTH);
|
||||||
if invoke_context.is_feature_active(&requestable_heap_size::id()) {
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&requestable_heap_size::id())
|
||||||
|
{
|
||||||
let _ = invoke_context
|
let _ = invoke_context
|
||||||
.get_compute_meter()
|
.get_compute_meter()
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
@ -450,8 +456,9 @@ fn process_loader_upgradeable_instruction(
|
||||||
return Err(InstructionError::InvalidArgument);
|
return Err(InstructionError::InvalidArgument);
|
||||||
}
|
}
|
||||||
|
|
||||||
let predrain_buffer =
|
let predrain_buffer = invoke_context
|
||||||
invoke_context.is_feature_active(&reduce_required_deploy_balance::id());
|
.feature_set
|
||||||
|
.is_active(&reduce_required_deploy_balance::id());
|
||||||
if predrain_buffer {
|
if predrain_buffer {
|
||||||
// Drain the Buffer account to payer before paying for programdata account
|
// Drain the Buffer account to payer before paying for programdata account
|
||||||
payer
|
payer
|
||||||
|
@ -1014,7 +1021,7 @@ impl Executor for BpfExecutor {
|
||||||
trace!("BPF Program Instruction Trace:\n{}", trace_string);
|
trace!("BPF Program Instruction Trace:\n{}", trace_string);
|
||||||
}
|
}
|
||||||
drop(vm);
|
drop(vm);
|
||||||
let (_returned_from_program_id, return_data) = invoke_context.get_return_data();
|
let (_returned_from_program_id, return_data) = &invoke_context.return_data;
|
||||||
if !return_data.is_empty() {
|
if !return_data.is_empty() {
|
||||||
stable_log::program_return(&log_collector, &program_id, return_data);
|
stable_log::program_return(&log_collector, &program_id, return_data);
|
||||||
}
|
}
|
||||||
|
@ -1049,15 +1056,18 @@ impl Executor for BpfExecutor {
|
||||||
&keyed_accounts[first_instruction_account + 1..],
|
&keyed_accounts[first_instruction_account + 1..],
|
||||||
parameter_bytes.as_slice(),
|
parameter_bytes.as_slice(),
|
||||||
&account_lengths,
|
&account_lengths,
|
||||||
invoke_context.is_feature_active(&do_support_realloc::id()),
|
invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&do_support_realloc::id()),
|
||||||
)?;
|
)?;
|
||||||
deserialize_time.stop();
|
deserialize_time.stop();
|
||||||
invoke_context.update_timing(
|
let timings = &mut invoke_context.timings;
|
||||||
serialize_time.as_us(),
|
timings.serialize_us = timings.serialize_us.saturating_add(serialize_time.as_us());
|
||||||
create_vm_time.as_us(),
|
timings.create_vm_us = timings.create_vm_us.saturating_add(create_vm_time.as_us());
|
||||||
execute_time.as_us(),
|
timings.execute_us = timings.execute_us.saturating_add(execute_time.as_us());
|
||||||
deserialize_time.as_us(),
|
timings.deserialize_us = timings
|
||||||
);
|
.deserialize_us
|
||||||
|
.saturating_add(deserialize_time.as_us());
|
||||||
stable_log::program_success(&log_collector, &program_id);
|
stable_log::program_success(&log_collector, &program_id);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -141,12 +141,18 @@ pub fn register_syscalls(
|
||||||
syscall_registry.register_syscall_by_name(b"sol_sha256", SyscallSha256::call)?;
|
syscall_registry.register_syscall_by_name(b"sol_sha256", SyscallSha256::call)?;
|
||||||
syscall_registry.register_syscall_by_name(b"sol_keccak256", SyscallKeccak256::call)?;
|
syscall_registry.register_syscall_by_name(b"sol_keccak256", SyscallKeccak256::call)?;
|
||||||
|
|
||||||
if invoke_context.is_feature_active(&secp256k1_recover_syscall_enabled::id()) {
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&secp256k1_recover_syscall_enabled::id())
|
||||||
|
{
|
||||||
syscall_registry
|
syscall_registry
|
||||||
.register_syscall_by_name(b"sol_secp256k1_recover", SyscallSecp256k1Recover::call)?;
|
.register_syscall_by_name(b"sol_secp256k1_recover", SyscallSecp256k1Recover::call)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
if invoke_context.is_feature_active(&blake3_syscall_enabled::id()) {
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&blake3_syscall_enabled::id())
|
||||||
|
{
|
||||||
syscall_registry.register_syscall_by_name(b"sol_blake3", SyscallBlake3::call)?;
|
syscall_registry.register_syscall_by_name(b"sol_blake3", SyscallBlake3::call)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +162,10 @@ pub fn register_syscalls(
|
||||||
b"sol_get_epoch_schedule_sysvar",
|
b"sol_get_epoch_schedule_sysvar",
|
||||||
SyscallGetEpochScheduleSysvar::call,
|
SyscallGetEpochScheduleSysvar::call,
|
||||||
)?;
|
)?;
|
||||||
if !invoke_context.is_feature_active(&disable_fees_sysvar::id()) {
|
if !invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&disable_fees_sysvar::id())
|
||||||
|
{
|
||||||
syscall_registry
|
syscall_registry
|
||||||
.register_syscall_by_name(b"sol_get_fees_sysvar", SyscallGetFeesSysvar::call)?;
|
.register_syscall_by_name(b"sol_get_fees_sysvar", SyscallGetFeesSysvar::call)?;
|
||||||
}
|
}
|
||||||
|
@ -178,7 +187,10 @@ pub fn register_syscalls(
|
||||||
syscall_registry.register_syscall_by_name(b"sol_alloc_free_", SyscallAllocFree::call)?;
|
syscall_registry.register_syscall_by_name(b"sol_alloc_free_", SyscallAllocFree::call)?;
|
||||||
|
|
||||||
// Return data
|
// Return data
|
||||||
if invoke_context.is_feature_active(&return_data_syscall_enabled::id()) {
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&return_data_syscall_enabled::id())
|
||||||
|
{
|
||||||
syscall_registry
|
syscall_registry
|
||||||
.register_syscall_by_name(b"sol_set_return_data", SyscallSetReturnData::call)?;
|
.register_syscall_by_name(b"sol_set_return_data", SyscallSetReturnData::call)?;
|
||||||
syscall_registry
|
syscall_registry
|
||||||
|
@ -186,7 +198,10 @@ pub fn register_syscalls(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log data
|
// Log data
|
||||||
if invoke_context.is_feature_active(&sol_log_data_syscall_enabled::id()) {
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&sol_log_data_syscall_enabled::id())
|
||||||
|
{
|
||||||
syscall_registry.register_syscall_by_name(b"sol_log_data", SyscallLogData::call)?;
|
syscall_registry.register_syscall_by_name(b"sol_log_data", SyscallLogData::call)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -212,15 +227,21 @@ pub fn bind_syscall_context_objects<'a, 'b>(
|
||||||
heap: AlignedMemory,
|
heap: AlignedMemory,
|
||||||
orig_data_lens: &'a [usize],
|
orig_data_lens: &'a [usize],
|
||||||
) -> Result<(), EbpfError<BpfError>> {
|
) -> Result<(), EbpfError<BpfError>> {
|
||||||
let is_blake3_syscall_active = invoke_context.is_feature_active(&blake3_syscall_enabled::id());
|
let is_blake3_syscall_active = invoke_context
|
||||||
let is_secp256k1_recover_syscall_active =
|
.feature_set
|
||||||
invoke_context.is_feature_active(&secp256k1_recover_syscall_enabled::id());
|
.is_active(&blake3_syscall_enabled::id());
|
||||||
let is_fee_sysvar_via_syscall_active =
|
let is_secp256k1_recover_syscall_active = invoke_context
|
||||||
!invoke_context.is_feature_active(&disable_fees_sysvar::id());
|
.feature_set
|
||||||
let is_return_data_syscall_active =
|
.is_active(&secp256k1_recover_syscall_enabled::id());
|
||||||
invoke_context.is_feature_active(&return_data_syscall_enabled::id());
|
let is_fee_sysvar_via_syscall_active = !invoke_context
|
||||||
let is_sol_log_data_syscall_active =
|
.feature_set
|
||||||
invoke_context.is_feature_active(&sol_log_data_syscall_enabled::id());
|
.is_active(&disable_fees_sysvar::id());
|
||||||
|
let is_return_data_syscall_active = invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&return_data_syscall_enabled::id());
|
||||||
|
let is_sol_log_data_syscall_active = invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&sol_log_data_syscall_enabled::id());
|
||||||
|
|
||||||
let loader_id = invoke_context
|
let loader_id = invoke_context
|
||||||
.get_loader()
|
.get_loader()
|
||||||
|
@ -1004,18 +1025,15 @@ fn get_sysvar<T: std::fmt::Debug + Sysvar + SysvarId>(
|
||||||
var_addr: u64,
|
var_addr: u64,
|
||||||
loader_id: &Pubkey,
|
loader_id: &Pubkey,
|
||||||
memory_mapping: &MemoryMapping,
|
memory_mapping: &MemoryMapping,
|
||||||
invoke_context: Rc<RefCell<&mut InvokeContext>>,
|
invoke_context: &mut InvokeContext,
|
||||||
) -> Result<u64, EbpfError<BpfError>> {
|
) -> Result<u64, EbpfError<BpfError>> {
|
||||||
let invoke_context = invoke_context
|
|
||||||
.try_borrow()
|
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed)?;
|
|
||||||
|
|
||||||
invoke_context
|
invoke_context
|
||||||
.get_compute_meter()
|
.get_compute_meter()
|
||||||
.consume(invoke_context.get_compute_budget().sysvar_base_cost + size_of::<T>() as u64)?;
|
.consume(invoke_context.get_compute_budget().sysvar_base_cost + size_of::<T>() as u64)?;
|
||||||
let var = translate_type_mut::<T>(memory_mapping, var_addr, loader_id)?;
|
let var = translate_type_mut::<T>(memory_mapping, var_addr, loader_id)?;
|
||||||
|
|
||||||
*var = solana_program_runtime::invoke_context::get_sysvar::<T>(*invoke_context, id)
|
*var = invoke_context
|
||||||
|
.get_sysvar::<T>(id)
|
||||||
.map_err(SyscallError::InstructionError)?;
|
.map_err(SyscallError::InstructionError)?;
|
||||||
|
|
||||||
Ok(SUCCESS)
|
Ok(SUCCESS)
|
||||||
|
@ -1036,9 +1054,9 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallGetClockSysvar<'a, 'b> {
|
||||||
memory_mapping: &MemoryMapping,
|
memory_mapping: &MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||||
) {
|
) {
|
||||||
let invoke_context = question_mark!(
|
let mut invoke_context = question_mark!(
|
||||||
self.invoke_context
|
self.invoke_context
|
||||||
.try_borrow()
|
.try_borrow_mut()
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||||
result
|
result
|
||||||
);
|
);
|
||||||
|
@ -1053,7 +1071,7 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallGetClockSysvar<'a, 'b> {
|
||||||
var_addr,
|
var_addr,
|
||||||
&loader_id,
|
&loader_id,
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
self.invoke_context.clone(),
|
&mut invoke_context,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1072,9 +1090,9 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallGetEpochScheduleSysvar<'a, 'b> {
|
||||||
memory_mapping: &MemoryMapping,
|
memory_mapping: &MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||||
) {
|
) {
|
||||||
let invoke_context = question_mark!(
|
let mut invoke_context = question_mark!(
|
||||||
self.invoke_context
|
self.invoke_context
|
||||||
.try_borrow()
|
.try_borrow_mut()
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||||
result
|
result
|
||||||
);
|
);
|
||||||
|
@ -1089,7 +1107,7 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallGetEpochScheduleSysvar<'a, 'b> {
|
||||||
var_addr,
|
var_addr,
|
||||||
&loader_id,
|
&loader_id,
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
self.invoke_context.clone(),
|
&mut invoke_context,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1109,9 +1127,9 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallGetFeesSysvar<'a, 'b> {
|
||||||
memory_mapping: &MemoryMapping,
|
memory_mapping: &MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||||
) {
|
) {
|
||||||
let invoke_context = question_mark!(
|
let mut invoke_context = question_mark!(
|
||||||
self.invoke_context
|
self.invoke_context
|
||||||
.try_borrow()
|
.try_borrow_mut()
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||||
result
|
result
|
||||||
);
|
);
|
||||||
|
@ -1126,7 +1144,7 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallGetFeesSysvar<'a, 'b> {
|
||||||
var_addr,
|
var_addr,
|
||||||
&loader_id,
|
&loader_id,
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
self.invoke_context.clone(),
|
&mut invoke_context,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1145,9 +1163,9 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallGetRentSysvar<'a, 'b> {
|
||||||
memory_mapping: &MemoryMapping,
|
memory_mapping: &MemoryMapping,
|
||||||
result: &mut Result<u64, EbpfError<BpfError>>,
|
result: &mut Result<u64, EbpfError<BpfError>>,
|
||||||
) {
|
) {
|
||||||
let invoke_context = question_mark!(
|
let mut invoke_context = question_mark!(
|
||||||
self.invoke_context
|
self.invoke_context
|
||||||
.try_borrow()
|
.try_borrow_mut()
|
||||||
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
.map_err(|_| SyscallError::InvokeContextBorrowFailed),
|
||||||
result
|
result
|
||||||
);
|
);
|
||||||
|
@ -1162,7 +1180,7 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallGetRentSysvar<'a, 'b> {
|
||||||
var_addr,
|
var_addr,
|
||||||
&loader_id,
|
&loader_id,
|
||||||
memory_mapping,
|
memory_mapping,
|
||||||
self.invoke_context.clone(),
|
&mut invoke_context,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1509,8 +1527,10 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallSecp256k1Recover<'a, 'b> {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let sig_parse_result =
|
let sig_parse_result = if invoke_context
|
||||||
if invoke_context.is_feature_active(&libsecp256k1_0_5_upgrade_enabled::id()) {
|
.feature_set
|
||||||
|
.is_active(&libsecp256k1_0_5_upgrade_enabled::id())
|
||||||
|
{
|
||||||
libsecp256k1::Signature::parse_standard_slice(signature)
|
libsecp256k1::Signature::parse_standard_slice(signature)
|
||||||
} else {
|
} else {
|
||||||
libsecp256k1::Signature::parse_overflowing_slice(signature)
|
libsecp256k1::Signature::parse_overflowing_slice(signature)
|
||||||
|
@ -2157,8 +2177,9 @@ fn get_translated_accounts<'a, T, F>(
|
||||||
where
|
where
|
||||||
F: Fn(&T, &InvokeContext) -> Result<CallerAccount<'a>, EbpfError<BpfError>>,
|
F: Fn(&T, &InvokeContext) -> Result<CallerAccount<'a>, EbpfError<BpfError>>,
|
||||||
{
|
{
|
||||||
let demote_program_write_locks =
|
let demote_program_write_locks = invoke_context
|
||||||
invoke_context.is_feature_active(&demote_program_write_locks::id());
|
.feature_set
|
||||||
|
.is_active(&demote_program_write_locks::id());
|
||||||
let keyed_accounts = invoke_context
|
let keyed_accounts = invoke_context
|
||||||
.get_instruction_keyed_accounts()
|
.get_instruction_keyed_accounts()
|
||||||
.map_err(SyscallError::InstructionError)?;
|
.map_err(SyscallError::InstructionError)?;
|
||||||
|
@ -2275,9 +2296,11 @@ fn check_authorized_program(
|
||||||
&& !(bpf_loader_upgradeable::is_upgrade_instruction(instruction_data)
|
&& !(bpf_loader_upgradeable::is_upgrade_instruction(instruction_data)
|
||||||
|| bpf_loader_upgradeable::is_set_authority_instruction(instruction_data)
|
|| bpf_loader_upgradeable::is_set_authority_instruction(instruction_data)
|
||||||
|| bpf_loader_upgradeable::is_close_instruction(instruction_data)))
|
|| bpf_loader_upgradeable::is_close_instruction(instruction_data)))
|
||||||
|| (invoke_context.is_feature_active(&prevent_calling_precompiles_as_programs::id())
|
|| (invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&prevent_calling_precompiles_as_programs::id())
|
||||||
&& is_precompile(program_id, |feature_id: &Pubkey| {
|
&& is_precompile(program_id, |feature_id: &Pubkey| {
|
||||||
invoke_context.is_feature_active(feature_id)
|
invoke_context.feature_set.is_active(feature_id)
|
||||||
}))
|
}))
|
||||||
{
|
{
|
||||||
return Err(SyscallError::ProgramNotSupported(*program_id).into());
|
return Err(SyscallError::ProgramNotSupported(*program_id).into());
|
||||||
|
@ -2299,7 +2322,9 @@ fn call<'a, 'b: 'a>(
|
||||||
invoke_context
|
invoke_context
|
||||||
.get_compute_meter()
|
.get_compute_meter()
|
||||||
.consume(invoke_context.get_compute_budget().invoke_units)?;
|
.consume(invoke_context.get_compute_budget().invoke_units)?;
|
||||||
let do_support_realloc = invoke_context.is_feature_active(&do_support_realloc::id());
|
let do_support_realloc = invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&do_support_realloc::id());
|
||||||
|
|
||||||
// Translate and verify caller's data
|
// Translate and verify caller's data
|
||||||
let loader_id = invoke_context
|
let loader_id = invoke_context
|
||||||
|
@ -2335,7 +2360,9 @@ fn call<'a, 'b: 'a>(
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Record the instruction
|
// Record the instruction
|
||||||
invoke_context.record_instruction(&instruction);
|
if let Some(instruction_recorder) = &invoke_context.instruction_recorder {
|
||||||
|
instruction_recorder.record_instruction(instruction);
|
||||||
|
}
|
||||||
|
|
||||||
// Process instruction
|
// Process instruction
|
||||||
invoke_context
|
invoke_context
|
||||||
|
@ -2453,12 +2480,13 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallSetReturnData<'a, 'b> {
|
||||||
)
|
)
|
||||||
.to_vec()
|
.to_vec()
|
||||||
};
|
};
|
||||||
question_mark!(
|
let program_id = question_mark!(
|
||||||
invoke_context
|
invoke_context
|
||||||
.set_return_data(return_data)
|
.get_caller()
|
||||||
.map_err(SyscallError::InstructionError),
|
.map_err(SyscallError::InstructionError),
|
||||||
result
|
result
|
||||||
);
|
);
|
||||||
|
invoke_context.return_data = (*program_id, return_data);
|
||||||
|
|
||||||
*result = Ok(0);
|
*result = Ok(0);
|
||||||
}
|
}
|
||||||
|
@ -2500,7 +2528,7 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallGetReturnData<'a, 'b> {
|
||||||
result
|
result
|
||||||
);
|
);
|
||||||
|
|
||||||
let (program_id, return_data) = invoke_context.get_return_data();
|
let (program_id, return_data) = &invoke_context.return_data;
|
||||||
length = length.min(return_data.len() as u64);
|
length = length.min(return_data.len() as u64);
|
||||||
if length != 0 {
|
if length != 0 {
|
||||||
question_mark!(
|
question_mark!(
|
||||||
|
@ -2522,7 +2550,7 @@ impl<'a, 'b> SyscallObject<BpfError> for SyscallGetReturnData<'a, 'b> {
|
||||||
result
|
result
|
||||||
);
|
);
|
||||||
|
|
||||||
program_id_result[0] = program_id;
|
program_id_result[0] = *program_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the actual length, rather the length returned
|
// Return the actual length, rather the length returned
|
||||||
|
@ -2618,10 +2646,8 @@ mod tests {
|
||||||
use solana_rbpf::{
|
use solana_rbpf::{
|
||||||
ebpf::HOST_ALIGN, memory_region::MemoryRegion, user_error::UserError, vm::Config,
|
ebpf::HOST_ALIGN, memory_region::MemoryRegion, user_error::UserError, vm::Config,
|
||||||
};
|
};
|
||||||
use solana_sdk::{
|
use solana_sdk::{bpf_loader, fee_calculator::FeeCalculator, hash::hashv};
|
||||||
bpf_loader, feature_set::FeatureSet, fee_calculator::FeeCalculator, hash::hashv,
|
use std::str::FromStr;
|
||||||
};
|
|
||||||
use std::{str::FromStr, sync::Arc};
|
|
||||||
|
|
||||||
macro_rules! assert_access_violation {
|
macro_rules! assert_access_violation {
|
||||||
($result:expr, $va:expr, $len:expr) => {
|
($result:expr, $va:expr, $len:expr) => {
|
||||||
|
@ -3529,13 +3555,9 @@ mod tests {
|
||||||
};
|
};
|
||||||
let mut data = vec![];
|
let mut data = vec![];
|
||||||
bincode::serialize_into(&mut data, &src_clock).unwrap();
|
bincode::serialize_into(&mut data, &src_clock).unwrap();
|
||||||
|
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
|
||||||
let sysvars = [(sysvar::clock::id(), data)];
|
let sysvars = [(sysvar::clock::id(), data)];
|
||||||
let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features(
|
invoke_context.sysvars = &sysvars;
|
||||||
&accounts,
|
|
||||||
&[],
|
|
||||||
&sysvars,
|
|
||||||
Arc::new(FeatureSet::all_enabled()),
|
|
||||||
);
|
|
||||||
invoke_context
|
invoke_context
|
||||||
.push(&message, &message.instructions[0], &[0], None)
|
.push(&message, &message.instructions[0], &[0], None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -3578,13 +3600,9 @@ mod tests {
|
||||||
};
|
};
|
||||||
let mut data = vec![];
|
let mut data = vec![];
|
||||||
bincode::serialize_into(&mut data, &src_epochschedule).unwrap();
|
bincode::serialize_into(&mut data, &src_epochschedule).unwrap();
|
||||||
|
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
|
||||||
let sysvars = [(sysvar::epoch_schedule::id(), data)];
|
let sysvars = [(sysvar::epoch_schedule::id(), data)];
|
||||||
let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features(
|
invoke_context.sysvars = &sysvars;
|
||||||
&accounts,
|
|
||||||
&[],
|
|
||||||
&sysvars,
|
|
||||||
Arc::new(FeatureSet::all_enabled()),
|
|
||||||
);
|
|
||||||
invoke_context
|
invoke_context
|
||||||
.push(&message, &message.instructions[0], &[0], None)
|
.push(&message, &message.instructions[0], &[0], None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -3634,13 +3652,9 @@ mod tests {
|
||||||
};
|
};
|
||||||
let mut data = vec![];
|
let mut data = vec![];
|
||||||
bincode::serialize_into(&mut data, &src_fees).unwrap();
|
bincode::serialize_into(&mut data, &src_fees).unwrap();
|
||||||
|
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
|
||||||
let sysvars = [(sysvar::fees::id(), data)];
|
let sysvars = [(sysvar::fees::id(), data)];
|
||||||
let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features(
|
invoke_context.sysvars = &sysvars;
|
||||||
&accounts,
|
|
||||||
&[],
|
|
||||||
&sysvars,
|
|
||||||
Arc::new(FeatureSet::all_enabled()),
|
|
||||||
);
|
|
||||||
invoke_context
|
invoke_context
|
||||||
.push(&message, &message.instructions[0], &[0], None)
|
.push(&message, &message.instructions[0], &[0], None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -3681,13 +3695,9 @@ mod tests {
|
||||||
};
|
};
|
||||||
let mut data = vec![];
|
let mut data = vec![];
|
||||||
bincode::serialize_into(&mut data, &src_rent).unwrap();
|
bincode::serialize_into(&mut data, &src_rent).unwrap();
|
||||||
|
let mut invoke_context = InvokeContext::new_mock(&accounts, &[]);
|
||||||
let sysvars = [(sysvar::rent::id(), data)];
|
let sysvars = [(sysvar::rent::id(), data)];
|
||||||
let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features(
|
invoke_context.sysvars = &sysvars;
|
||||||
&accounts,
|
|
||||||
&[],
|
|
||||||
&sysvars,
|
|
||||||
Arc::new(FeatureSet::all_enabled()),
|
|
||||||
);
|
|
||||||
invoke_context
|
invoke_context
|
||||||
.push(&message, &message.instructions[0], &[0], None)
|
.push(&message, &message.instructions[0], &[0], None)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -3949,9 +3959,14 @@ mod tests {
|
||||||
.get_compute_budget()
|
.get_compute_budget()
|
||||||
.create_program_address_units;
|
.create_program_address_units;
|
||||||
let address = bpf_loader_upgradeable::id();
|
let address = bpf_loader_upgradeable::id();
|
||||||
|
let max_tries = 256; // one per seed
|
||||||
|
|
||||||
for _ in 0..1_000 {
|
for _ in 0..1_000 {
|
||||||
let address = Pubkey::new_unique();
|
let address = Pubkey::new_unique();
|
||||||
|
invoke_context
|
||||||
|
.get_compute_meter()
|
||||||
|
.borrow_mut()
|
||||||
|
.mock_set_remaining(cost * max_tries);
|
||||||
let (found_address, bump_seed) =
|
let (found_address, bump_seed) =
|
||||||
try_find_program_address(&mut invoke_context, &[b"Lil'", b"Bits"], &address)
|
try_find_program_address(&mut invoke_context, &[b"Lil'", b"Bits"], &address)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -3966,7 +3981,6 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let max_tries = 256; // one per seed
|
|
||||||
let seeds: &[&[u8]] = &[b""];
|
let seeds: &[&[u8]] = &[b""];
|
||||||
invoke_context
|
invoke_context
|
||||||
.get_compute_meter()
|
.get_compute_meter()
|
||||||
|
|
|
@ -100,7 +100,10 @@ pub fn process_instruction(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if invoke_context.is_feature_active(&feature_set::dedupe_config_program_signers::id()) {
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&feature_set::dedupe_config_program_signers::id())
|
||||||
|
{
|
||||||
let total_new_keys = key_list.keys.len();
|
let total_new_keys = key_list.keys.len();
|
||||||
let unique_new_keys = key_list.keys.into_iter().collect::<BTreeSet<_>>();
|
let unique_new_keys = key_list.keys.into_iter().collect::<BTreeSet<_>>();
|
||||||
if unique_new_keys.len() != total_new_keys {
|
if unique_new_keys.len() != total_new_keys {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use {
|
use {
|
||||||
crate::{config, stake_state::StakeAccount},
|
crate::{config, stake_state::StakeAccount},
|
||||||
log::*,
|
log::*,
|
||||||
solana_program_runtime::invoke_context::{get_sysvar, InvokeContext},
|
solana_program_runtime::invoke_context::InvokeContext,
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
feature_set,
|
feature_set,
|
||||||
instruction::InstructionError,
|
instruction::InstructionError,
|
||||||
|
@ -48,9 +48,9 @@ pub fn process_instruction(
|
||||||
)?)?,
|
)?)?,
|
||||||
),
|
),
|
||||||
StakeInstruction::Authorize(authorized_pubkey, stake_authorize) => {
|
StakeInstruction::Authorize(authorized_pubkey, stake_authorize) => {
|
||||||
let require_custodian_for_locked_stake_authorize = invoke_context.is_feature_active(
|
let require_custodian_for_locked_stake_authorize = invoke_context
|
||||||
&feature_set::require_custodian_for_locked_stake_authorize::id(),
|
.feature_set
|
||||||
);
|
.is_active(&feature_set::require_custodian_for_locked_stake_authorize::id());
|
||||||
|
|
||||||
if require_custodian_for_locked_stake_authorize {
|
if require_custodian_for_locked_stake_authorize {
|
||||||
let clock = from_keyed_account::<Clock>(keyed_account_at_index(
|
let clock = from_keyed_account::<Clock>(keyed_account_at_index(
|
||||||
|
@ -86,9 +86,9 @@ pub fn process_instruction(
|
||||||
StakeInstruction::AuthorizeWithSeed(args) => {
|
StakeInstruction::AuthorizeWithSeed(args) => {
|
||||||
let authority_base =
|
let authority_base =
|
||||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||||
let require_custodian_for_locked_stake_authorize = invoke_context.is_feature_active(
|
let require_custodian_for_locked_stake_authorize = invoke_context
|
||||||
&feature_set::require_custodian_for_locked_stake_authorize::id(),
|
.feature_set
|
||||||
);
|
.is_active(&feature_set::require_custodian_for_locked_stake_authorize::id());
|
||||||
|
|
||||||
if require_custodian_for_locked_stake_authorize {
|
if require_custodian_for_locked_stake_authorize {
|
||||||
let clock = from_keyed_account::<Clock>(keyed_account_at_index(
|
let clock = from_keyed_account::<Clock>(keyed_account_at_index(
|
||||||
|
@ -124,8 +124,9 @@ pub fn process_instruction(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StakeInstruction::DelegateStake => {
|
StakeInstruction::DelegateStake => {
|
||||||
let can_reverse_deactivation =
|
let can_reverse_deactivation = invoke_context
|
||||||
invoke_context.is_feature_active(&feature_set::stake_program_v4::id());
|
.feature_set
|
||||||
|
.is_active(&feature_set::stake_program_v4::id());
|
||||||
let vote = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
let vote = keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||||
|
|
||||||
me.delegate(
|
me.delegate(
|
||||||
|
@ -154,8 +155,9 @@ pub fn process_instruction(
|
||||||
StakeInstruction::Merge => {
|
StakeInstruction::Merge => {
|
||||||
let source_stake =
|
let source_stake =
|
||||||
&keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
&keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||||
let can_merge_expired_lockups =
|
let can_merge_expired_lockups = invoke_context
|
||||||
invoke_context.is_feature_active(&feature_set::stake_program_v4::id());
|
.feature_set
|
||||||
|
.is_active(&feature_set::stake_program_v4::id());
|
||||||
me.merge(
|
me.merge(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
source_stake,
|
source_stake,
|
||||||
|
@ -186,7 +188,9 @@ pub fn process_instruction(
|
||||||
)?)?,
|
)?)?,
|
||||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 4)?,
|
keyed_account_at_index(keyed_accounts, first_instruction_account + 4)?,
|
||||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 5).ok(),
|
keyed_account_at_index(keyed_accounts, first_instruction_account + 5).ok(),
|
||||||
invoke_context.is_feature_active(&feature_set::stake_program_v4::id()),
|
invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&feature_set::stake_program_v4::id()),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
StakeInstruction::Deactivate => me.deactivate(
|
StakeInstruction::Deactivate => me.deactivate(
|
||||||
|
@ -197,15 +201,20 @@ pub fn process_instruction(
|
||||||
&signers,
|
&signers,
|
||||||
),
|
),
|
||||||
StakeInstruction::SetLockup(lockup) => {
|
StakeInstruction::SetLockup(lockup) => {
|
||||||
let clock = if invoke_context.is_feature_active(&feature_set::stake_program_v4::id()) {
|
let clock = if invoke_context
|
||||||
Some(get_sysvar::<Clock>(invoke_context, &sysvar::clock::id())?)
|
.feature_set
|
||||||
|
.is_active(&feature_set::stake_program_v4::id())
|
||||||
|
{
|
||||||
|
Some(invoke_context.get_sysvar::<Clock>(&sysvar::clock::id())?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
me.set_lockup(&lockup, &signers, clock.as_ref())
|
me.set_lockup(&lockup, &signers, clock.as_ref())
|
||||||
}
|
}
|
||||||
StakeInstruction::InitializeChecked => {
|
StakeInstruction::InitializeChecked => {
|
||||||
if invoke_context.is_feature_active(&feature_set::vote_stake_checked_instructions::id())
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&feature_set::vote_stake_checked_instructions::id())
|
||||||
{
|
{
|
||||||
let authorized = Authorized {
|
let authorized = Authorized {
|
||||||
staker: *keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?
|
staker: *keyed_account_at_index(keyed_accounts, first_instruction_account + 2)?
|
||||||
|
@ -231,7 +240,9 @@ pub fn process_instruction(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StakeInstruction::AuthorizeChecked(stake_authorize) => {
|
StakeInstruction::AuthorizeChecked(stake_authorize) => {
|
||||||
if invoke_context.is_feature_active(&feature_set::vote_stake_checked_instructions::id())
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&feature_set::vote_stake_checked_instructions::id())
|
||||||
{
|
{
|
||||||
let clock = from_keyed_account::<Clock>(keyed_account_at_index(
|
let clock = from_keyed_account::<Clock>(keyed_account_at_index(
|
||||||
keyed_accounts,
|
keyed_accounts,
|
||||||
|
@ -261,7 +272,9 @@ pub fn process_instruction(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StakeInstruction::AuthorizeCheckedWithSeed(args) => {
|
StakeInstruction::AuthorizeCheckedWithSeed(args) => {
|
||||||
if invoke_context.is_feature_active(&feature_set::vote_stake_checked_instructions::id())
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&feature_set::vote_stake_checked_instructions::id())
|
||||||
{
|
{
|
||||||
let authority_base =
|
let authority_base =
|
||||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
keyed_account_at_index(keyed_accounts, first_instruction_account + 1)?;
|
||||||
|
@ -293,7 +306,9 @@ pub fn process_instruction(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StakeInstruction::SetLockupChecked(lockup_checked) => {
|
StakeInstruction::SetLockupChecked(lockup_checked) => {
|
||||||
if invoke_context.is_feature_active(&feature_set::vote_stake_checked_instructions::id())
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&feature_set::vote_stake_checked_instructions::id())
|
||||||
{
|
{
|
||||||
let custodian = if let Ok(custodian) =
|
let custodian = if let Ok(custodian) =
|
||||||
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)
|
keyed_account_at_index(keyed_accounts, first_instruction_account + 2)
|
||||||
|
@ -312,7 +327,7 @@ pub fn process_instruction(
|
||||||
epoch: lockup_checked.epoch,
|
epoch: lockup_checked.epoch,
|
||||||
custodian,
|
custodian,
|
||||||
};
|
};
|
||||||
let clock = Some(get_sysvar::<Clock>(invoke_context, &sysvar::clock::id())?);
|
let clock = Some(invoke_context.get_sysvar::<Clock>(&sysvar::clock::id())?);
|
||||||
me.set_lockup(&lockup, &signers, clock.as_ref())
|
me.set_lockup(&lockup, &signers, clock.as_ref())
|
||||||
} else {
|
} else {
|
||||||
Err(InstructionError::InvalidInstructionData)
|
Err(InstructionError::InvalidInstructionData)
|
||||||
|
@ -331,7 +346,6 @@ mod tests {
|
||||||
};
|
};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::{self, AccountSharedData},
|
account::{self, AccountSharedData},
|
||||||
feature_set::FeatureSet,
|
|
||||||
instruction::{AccountMeta, Instruction},
|
instruction::{AccountMeta, Instruction},
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
|
@ -342,7 +356,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
sysvar::{stake_history::StakeHistory, Sysvar},
|
sysvar::{stake_history::StakeHistory, Sysvar},
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, rc::Rc, str::FromStr, sync::Arc};
|
use std::{cell::RefCell, rc::Rc, str::FromStr};
|
||||||
|
|
||||||
fn create_default_account() -> Rc<RefCell<AccountSharedData>> {
|
fn create_default_account() -> Rc<RefCell<AccountSharedData>> {
|
||||||
AccountSharedData::new_ref(0, 0, &Pubkey::new_unique())
|
AccountSharedData::new_ref(0, 0, &Pubkey::new_unique())
|
||||||
|
@ -415,13 +429,9 @@ mod tests {
|
||||||
preparation.accounts.push((id(), processor_account));
|
preparation.accounts.push((id(), processor_account));
|
||||||
let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of());
|
let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of());
|
||||||
bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap();
|
bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap();
|
||||||
|
let mut invoke_context = InvokeContext::new_mock(&preparation.accounts, &[]);
|
||||||
let sysvars = [(sysvar::clock::id(), data)];
|
let sysvars = [(sysvar::clock::id(), data)];
|
||||||
let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features(
|
invoke_context.sysvars = &sysvars;
|
||||||
&preparation.accounts,
|
|
||||||
&[],
|
|
||||||
&sysvars,
|
|
||||||
Arc::new(FeatureSet::all_enabled()),
|
|
||||||
);
|
|
||||||
invoke_context.push(
|
invoke_context.push(
|
||||||
&preparation.message,
|
&preparation.message,
|
||||||
&preparation.message.instructions[0],
|
&preparation.message.instructions[0],
|
||||||
|
@ -1065,13 +1075,9 @@ mod tests {
|
||||||
preparation.accounts.push((id(), processor_account));
|
preparation.accounts.push((id(), processor_account));
|
||||||
let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of());
|
let mut data = Vec::with_capacity(sysvar::clock::Clock::size_of());
|
||||||
bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap();
|
bincode::serialize_into(&mut data, &sysvar::clock::Clock::default()).unwrap();
|
||||||
|
let mut invoke_context = InvokeContext::new_mock(&preparation.accounts, &[]);
|
||||||
let sysvars = [(sysvar::clock::id(), data)];
|
let sysvars = [(sysvar::clock::id(), data)];
|
||||||
let mut invoke_context = InvokeContext::new_mock_with_sysvars_and_features(
|
invoke_context.sysvars = &sysvars;
|
||||||
&preparation.accounts,
|
|
||||||
&[],
|
|
||||||
&sysvars,
|
|
||||||
Arc::new(FeatureSet::all_enabled()),
|
|
||||||
);
|
|
||||||
invoke_context
|
invoke_context
|
||||||
.push(
|
.push(
|
||||||
&preparation.message,
|
&preparation.message,
|
||||||
|
|
|
@ -978,7 +978,8 @@ impl MergeKind {
|
||||||
.zip(source.active_stake())
|
.zip(source.active_stake())
|
||||||
.map(|(stake, source)| {
|
.map(|(stake, source)| {
|
||||||
if invoke_context
|
if invoke_context
|
||||||
.is_feature_active(&stake_merge_with_unmatched_credits_observed::id())
|
.feature_set
|
||||||
|
.is_active(&stake_merge_with_unmatched_credits_observed::id())
|
||||||
{
|
{
|
||||||
Self::active_delegations_can_merge(
|
Self::active_delegations_can_merge(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
|
@ -1038,7 +1039,10 @@ fn merge_delegation_stake_and_credits_observed(
|
||||||
absorbed_lamports: u64,
|
absorbed_lamports: u64,
|
||||||
absorbed_credits_observed: u64,
|
absorbed_credits_observed: u64,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
if invoke_context.is_feature_active(&stake_merge_with_unmatched_credits_observed::id()) {
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&stake_merge_with_unmatched_credits_observed::id())
|
||||||
|
{
|
||||||
stake.credits_observed =
|
stake.credits_observed =
|
||||||
stake_weighted_credits_observed(stake, absorbed_lamports, absorbed_credits_observed)
|
stake_weighted_credits_observed(stake, absorbed_lamports, absorbed_credits_observed)
|
||||||
.ok_or(InstructionError::ArithmeticOverflow)?;
|
.ok_or(InstructionError::ArithmeticOverflow)?;
|
||||||
|
|
|
@ -378,7 +378,9 @@ pub fn process_instruction(
|
||||||
vote_state::withdraw(me, lamports, to, &signers)
|
vote_state::withdraw(me, lamports, to, &signers)
|
||||||
}
|
}
|
||||||
VoteInstruction::AuthorizeChecked(vote_authorize) => {
|
VoteInstruction::AuthorizeChecked(vote_authorize) => {
|
||||||
if invoke_context.is_feature_active(&feature_set::vote_stake_checked_instructions::id())
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&feature_set::vote_stake_checked_instructions::id())
|
||||||
{
|
{
|
||||||
let voter_pubkey =
|
let voter_pubkey =
|
||||||
&keyed_account_at_index(keyed_accounts, first_instruction_account + 3)?
|
&keyed_account_at_index(keyed_accounts, first_instruction_account + 3)?
|
||||||
|
|
|
@ -71,9 +71,7 @@ use solana_measure::measure::Measure;
|
||||||
use solana_metrics::{inc_new_counter_debug, inc_new_counter_info};
|
use solana_metrics::{inc_new_counter_debug, inc_new_counter_info};
|
||||||
use solana_program_runtime::{
|
use solana_program_runtime::{
|
||||||
instruction_recorder::InstructionRecorder,
|
instruction_recorder::InstructionRecorder,
|
||||||
invoke_context::{
|
invoke_context::{BuiltinProgram, Executor, Executors, ProcessInstructionWithContext},
|
||||||
BuiltinProgram, ComputeMeter, Executor, Executors, ProcessInstructionWithContext,
|
|
||||||
},
|
|
||||||
log_collector::LogCollector,
|
log_collector::LogCollector,
|
||||||
timings::ExecuteDetailsTimings,
|
timings::ExecuteDetailsTimings,
|
||||||
};
|
};
|
||||||
|
@ -3871,8 +3869,6 @@ impl Bank {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
let compute_meter = ComputeMeter::new_ref(compute_budget.max_units);
|
|
||||||
|
|
||||||
let (blockhash, lamports_per_signature) =
|
let (blockhash, lamports_per_signature) =
|
||||||
self.last_blockhash_and_lamports_per_signature();
|
self.last_blockhash_and_lamports_per_signature();
|
||||||
|
|
||||||
|
@ -3888,7 +3884,6 @@ impl Bank {
|
||||||
instruction_recorders.as_deref(),
|
instruction_recorders.as_deref(),
|
||||||
feature_set,
|
feature_set,
|
||||||
compute_budget,
|
compute_budget,
|
||||||
compute_meter,
|
|
||||||
&mut timings.details,
|
&mut timings.details,
|
||||||
&*self.sysvar_cache.read().unwrap(),
|
&*self.sysvar_cache.read().unwrap(),
|
||||||
blockhash,
|
blockhash,
|
||||||
|
|
|
@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use solana_measure::measure::Measure;
|
use solana_measure::measure::Measure;
|
||||||
use solana_program_runtime::{
|
use solana_program_runtime::{
|
||||||
instruction_recorder::InstructionRecorder,
|
instruction_recorder::InstructionRecorder,
|
||||||
invoke_context::{BuiltinProgram, ComputeMeter, Executors, InvokeContext},
|
invoke_context::{BuiltinProgram, Executors, InvokeContext},
|
||||||
log_collector::LogCollector,
|
log_collector::LogCollector,
|
||||||
timings::ExecuteDetailsTimings,
|
timings::ExecuteDetailsTimings,
|
||||||
};
|
};
|
||||||
|
@ -50,7 +50,6 @@ impl MessageProcessor {
|
||||||
instruction_recorders: Option<&[InstructionRecorder]>,
|
instruction_recorders: Option<&[InstructionRecorder]>,
|
||||||
feature_set: Arc<FeatureSet>,
|
feature_set: Arc<FeatureSet>,
|
||||||
compute_budget: ComputeBudget,
|
compute_budget: ComputeBudget,
|
||||||
compute_meter: Rc<RefCell<ComputeMeter>>,
|
|
||||||
timings: &mut ExecuteDetailsTimings,
|
timings: &mut ExecuteDetailsTimings,
|
||||||
sysvars: &[(Pubkey, Vec<u8>)],
|
sysvars: &[(Pubkey, Vec<u8>)],
|
||||||
blockhash: Hash,
|
blockhash: Hash,
|
||||||
|
@ -63,9 +62,7 @@ impl MessageProcessor {
|
||||||
sysvars,
|
sysvars,
|
||||||
log_collector,
|
log_collector,
|
||||||
compute_budget,
|
compute_budget,
|
||||||
compute_meter,
|
|
||||||
executors,
|
executors,
|
||||||
instruction_recorders,
|
|
||||||
feature_set,
|
feature_set,
|
||||||
blockhash,
|
blockhash,
|
||||||
lamports_per_signature,
|
lamports_per_signature,
|
||||||
|
@ -79,8 +76,10 @@ impl MessageProcessor {
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
let program_id = instruction.program_id(&message.account_keys);
|
let program_id = instruction.program_id(&message.account_keys);
|
||||||
if invoke_context.is_feature_active(&prevent_calling_precompiles_as_programs::id())
|
if invoke_context
|
||||||
&& is_precompile(program_id, |id| invoke_context.is_feature_active(id))
|
.feature_set
|
||||||
|
.is_active(&prevent_calling_precompiles_as_programs::id())
|
||||||
|
&& is_precompile(program_id, |id| invoke_context.feature_set.is_active(id))
|
||||||
{
|
{
|
||||||
// Precompiled programs don't have an instruction processor
|
// Precompiled programs don't have an instruction processor
|
||||||
continue;
|
continue;
|
||||||
|
@ -99,7 +98,10 @@ impl MessageProcessor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
invoke_context.set_instruction_index(instruction_index);
|
if let Some(instruction_recorders) = instruction_recorders {
|
||||||
|
invoke_context.instruction_recorder =
|
||||||
|
Some(&instruction_recorders[instruction_index]);
|
||||||
|
}
|
||||||
let result = invoke_context
|
let result = invoke_context
|
||||||
.push(message, instruction, program_indices, None)
|
.push(message, instruction, program_indices, None)
|
||||||
.and_then(|_| {
|
.and_then(|_| {
|
||||||
|
@ -134,7 +136,6 @@ impl MessageProcessor {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::rent_collector::RentCollector;
|
use crate::rent_collector::RentCollector;
|
||||||
use solana_program_runtime::invoke_context::ComputeMeter;
|
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::ReadableAccount,
|
account::ReadableAccount,
|
||||||
instruction::{AccountMeta, Instruction, InstructionError},
|
instruction::{AccountMeta, Instruction, InstructionError},
|
||||||
|
@ -246,7 +247,6 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
Arc::new(FeatureSet::all_enabled()),
|
Arc::new(FeatureSet::all_enabled()),
|
||||||
ComputeBudget::new(),
|
ComputeBudget::new(),
|
||||||
ComputeMeter::new_ref(std::i64::MAX as u64),
|
|
||||||
&mut ExecuteDetailsTimings::default(),
|
&mut ExecuteDetailsTimings::default(),
|
||||||
&[],
|
&[],
|
||||||
Hash::default(),
|
Hash::default(),
|
||||||
|
@ -276,7 +276,6 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
Arc::new(FeatureSet::all_enabled()),
|
Arc::new(FeatureSet::all_enabled()),
|
||||||
ComputeBudget::new(),
|
ComputeBudget::new(),
|
||||||
ComputeMeter::new_ref(std::i64::MAX as u64),
|
|
||||||
&mut ExecuteDetailsTimings::default(),
|
&mut ExecuteDetailsTimings::default(),
|
||||||
&[],
|
&[],
|
||||||
Hash::default(),
|
Hash::default(),
|
||||||
|
@ -310,7 +309,6 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
Arc::new(FeatureSet::all_enabled()),
|
Arc::new(FeatureSet::all_enabled()),
|
||||||
ComputeBudget::new(),
|
ComputeBudget::new(),
|
||||||
ComputeMeter::new_ref(std::i64::MAX as u64),
|
|
||||||
&mut ExecuteDetailsTimings::default(),
|
&mut ExecuteDetailsTimings::default(),
|
||||||
&[],
|
&[],
|
||||||
Hash::default(),
|
Hash::default(),
|
||||||
|
@ -455,7 +453,6 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
Arc::new(FeatureSet::all_enabled()),
|
Arc::new(FeatureSet::all_enabled()),
|
||||||
ComputeBudget::new(),
|
ComputeBudget::new(),
|
||||||
ComputeMeter::new_ref(std::i64::MAX as u64),
|
|
||||||
&mut ExecuteDetailsTimings::default(),
|
&mut ExecuteDetailsTimings::default(),
|
||||||
&[],
|
&[],
|
||||||
Hash::default(),
|
Hash::default(),
|
||||||
|
@ -489,7 +486,6 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
Arc::new(FeatureSet::all_enabled()),
|
Arc::new(FeatureSet::all_enabled()),
|
||||||
ComputeBudget::new(),
|
ComputeBudget::new(),
|
||||||
ComputeMeter::new_ref(std::i64::MAX as u64),
|
|
||||||
&mut ExecuteDetailsTimings::default(),
|
&mut ExecuteDetailsTimings::default(),
|
||||||
&[],
|
&[],
|
||||||
Hash::default(),
|
Hash::default(),
|
||||||
|
@ -520,7 +516,6 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
Arc::new(FeatureSet::all_enabled()),
|
Arc::new(FeatureSet::all_enabled()),
|
||||||
ComputeBudget::new(),
|
ComputeBudget::new(),
|
||||||
ComputeMeter::new_ref(std::i64::MAX as u64),
|
|
||||||
&mut ExecuteDetailsTimings::default(),
|
&mut ExecuteDetailsTimings::default(),
|
||||||
&[],
|
&[],
|
||||||
Hash::default(),
|
Hash::default(),
|
||||||
|
@ -578,7 +573,6 @@ mod tests {
|
||||||
None,
|
None,
|
||||||
Arc::new(FeatureSet::all_enabled()),
|
Arc::new(FeatureSet::all_enabled()),
|
||||||
ComputeBudget::new(),
|
ComputeBudget::new(),
|
||||||
ComputeMeter::new_ref(std::i64::MAX as u64),
|
|
||||||
&mut ExecuteDetailsTimings::default(),
|
&mut ExecuteDetailsTimings::default(),
|
||||||
&[],
|
&[],
|
||||||
Hash::default(),
|
Hash::default(),
|
||||||
|
|
|
@ -47,9 +47,14 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> {
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let merge_nonce_error_into_system_error = invoke_context
|
let merge_nonce_error_into_system_error = invoke_context
|
||||||
.is_feature_active(&feature_set::merge_nonce_error_into_system_error::id());
|
.feature_set
|
||||||
|
.is_active(&feature_set::merge_nonce_error_into_system_error::id());
|
||||||
|
|
||||||
if invoke_context.is_feature_active(&nonce_must_be_writable::id()) && !self.is_writable() {
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&nonce_must_be_writable::id())
|
||||||
|
&& !self.is_writable()
|
||||||
|
{
|
||||||
ic_msg!(
|
ic_msg!(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
"Advance nonce account: Account {} must be writeable",
|
"Advance nonce account: Account {} must be writeable",
|
||||||
|
@ -69,7 +74,7 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> {
|
||||||
);
|
);
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
let recent_blockhash = *invoke_context.get_blockhash();
|
let recent_blockhash = invoke_context.blockhash;
|
||||||
if data.blockhash == recent_blockhash {
|
if data.blockhash == recent_blockhash {
|
||||||
ic_msg!(
|
ic_msg!(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
|
@ -84,7 +89,7 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> {
|
||||||
let new_data = nonce::state::Data::new(
|
let new_data = nonce::state::Data::new(
|
||||||
data.authority,
|
data.authority,
|
||||||
recent_blockhash,
|
recent_blockhash,
|
||||||
invoke_context.get_lamports_per_signature(),
|
invoke_context.lamports_per_signature,
|
||||||
);
|
);
|
||||||
self.set_state(&Versions::new_current(State::Initialized(new_data)))
|
self.set_state(&Versions::new_current(State::Initialized(new_data)))
|
||||||
}
|
}
|
||||||
|
@ -111,9 +116,14 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> {
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let merge_nonce_error_into_system_error = invoke_context
|
let merge_nonce_error_into_system_error = invoke_context
|
||||||
.is_feature_active(&feature_set::merge_nonce_error_into_system_error::id());
|
.feature_set
|
||||||
|
.is_active(&feature_set::merge_nonce_error_into_system_error::id());
|
||||||
|
|
||||||
if invoke_context.is_feature_active(&nonce_must_be_writable::id()) && !self.is_writable() {
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&nonce_must_be_writable::id())
|
||||||
|
&& !self.is_writable()
|
||||||
|
{
|
||||||
ic_msg!(
|
ic_msg!(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
"Withdraw nonce account: Account {} must be writeable",
|
"Withdraw nonce account: Account {} must be writeable",
|
||||||
|
@ -137,7 +147,7 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> {
|
||||||
}
|
}
|
||||||
State::Initialized(ref data) => {
|
State::Initialized(ref data) => {
|
||||||
if lamports == self.lamports()? {
|
if lamports == self.lamports()? {
|
||||||
if data.blockhash == *invoke_context.get_blockhash() {
|
if data.blockhash == invoke_context.blockhash {
|
||||||
ic_msg!(
|
ic_msg!(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
"Withdraw nonce account: nonce can only advance once per slot"
|
"Withdraw nonce account: nonce can only advance once per slot"
|
||||||
|
@ -197,9 +207,14 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> {
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let merge_nonce_error_into_system_error = invoke_context
|
let merge_nonce_error_into_system_error = invoke_context
|
||||||
.is_feature_active(&feature_set::merge_nonce_error_into_system_error::id());
|
.feature_set
|
||||||
|
.is_active(&feature_set::merge_nonce_error_into_system_error::id());
|
||||||
|
|
||||||
if invoke_context.is_feature_active(&nonce_must_be_writable::id()) && !self.is_writable() {
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&nonce_must_be_writable::id())
|
||||||
|
&& !self.is_writable()
|
||||||
|
{
|
||||||
ic_msg!(
|
ic_msg!(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
"Initialize nonce account: Account {} must be writeable",
|
"Initialize nonce account: Account {} must be writeable",
|
||||||
|
@ -222,8 +237,8 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> {
|
||||||
}
|
}
|
||||||
let data = nonce::state::Data::new(
|
let data = nonce::state::Data::new(
|
||||||
*nonce_authority,
|
*nonce_authority,
|
||||||
*invoke_context.get_blockhash(),
|
invoke_context.blockhash,
|
||||||
invoke_context.get_lamports_per_signature(),
|
invoke_context.lamports_per_signature,
|
||||||
);
|
);
|
||||||
self.set_state(&Versions::new_current(State::Initialized(data)))
|
self.set_state(&Versions::new_current(State::Initialized(data)))
|
||||||
}
|
}
|
||||||
|
@ -248,9 +263,14 @@ impl<'a> NonceKeyedAccount for KeyedAccount<'a> {
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let merge_nonce_error_into_system_error = invoke_context
|
let merge_nonce_error_into_system_error = invoke_context
|
||||||
.is_feature_active(&feature_set::merge_nonce_error_into_system_error::id());
|
.feature_set
|
||||||
|
.is_active(&feature_set::merge_nonce_error_into_system_error::id());
|
||||||
|
|
||||||
if invoke_context.is_feature_active(&nonce_must_be_writable::id()) && !self.is_writable() {
|
if invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&nonce_must_be_writable::id())
|
||||||
|
&& !self.is_writable()
|
||||||
|
{
|
||||||
ic_msg!(
|
ic_msg!(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
"Authorize nonce account: Account {} must be writeable",
|
"Authorize nonce account: Account {} must be writeable",
|
||||||
|
@ -325,8 +345,8 @@ mod test {
|
||||||
fn create_invoke_context_with_blockhash<'a>(seed: usize) -> InvokeContext<'a> {
|
fn create_invoke_context_with_blockhash<'a>(seed: usize) -> InvokeContext<'a> {
|
||||||
let mut invoke_context = InvokeContext::new_mock(&[], &[]);
|
let mut invoke_context = InvokeContext::new_mock(&[], &[]);
|
||||||
let (blockhash, lamports_per_signature) = create_test_blockhash(seed);
|
let (blockhash, lamports_per_signature) = create_test_blockhash(seed);
|
||||||
invoke_context.set_blockhash(blockhash);
|
invoke_context.blockhash = blockhash;
|
||||||
invoke_context.set_lamports_per_signature(lamports_per_signature);
|
invoke_context.lamports_per_signature = lamports_per_signature;
|
||||||
invoke_context
|
invoke_context
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -364,8 +384,8 @@ mod test {
|
||||||
.convert_to_current();
|
.convert_to_current();
|
||||||
let data = nonce::state::Data::new(
|
let data = nonce::state::Data::new(
|
||||||
data.authority,
|
data.authority,
|
||||||
*invoke_context.get_blockhash(),
|
invoke_context.blockhash,
|
||||||
invoke_context.get_lamports_per_signature(),
|
invoke_context.lamports_per_signature,
|
||||||
);
|
);
|
||||||
// First nonce instruction drives state from Uninitialized to Initialized
|
// First nonce instruction drives state from Uninitialized to Initialized
|
||||||
assert_eq!(state, State::Initialized(data.clone()));
|
assert_eq!(state, State::Initialized(data.clone()));
|
||||||
|
@ -378,8 +398,8 @@ mod test {
|
||||||
.convert_to_current();
|
.convert_to_current();
|
||||||
let data = nonce::state::Data::new(
|
let data = nonce::state::Data::new(
|
||||||
data.authority,
|
data.authority,
|
||||||
*invoke_context.get_blockhash(),
|
invoke_context.blockhash,
|
||||||
invoke_context.get_lamports_per_signature(),
|
invoke_context.lamports_per_signature,
|
||||||
);
|
);
|
||||||
// Second nonce instruction consumes and replaces stored nonce
|
// Second nonce instruction consumes and replaces stored nonce
|
||||||
assert_eq!(state, State::Initialized(data.clone()));
|
assert_eq!(state, State::Initialized(data.clone()));
|
||||||
|
@ -392,8 +412,8 @@ mod test {
|
||||||
.convert_to_current();
|
.convert_to_current();
|
||||||
let data = nonce::state::Data::new(
|
let data = nonce::state::Data::new(
|
||||||
data.authority,
|
data.authority,
|
||||||
*invoke_context.get_blockhash(),
|
invoke_context.blockhash,
|
||||||
invoke_context.get_lamports_per_signature(),
|
invoke_context.lamports_per_signature,
|
||||||
);
|
);
|
||||||
// Third nonce instruction for fun and profit
|
// Third nonce instruction for fun and profit
|
||||||
assert_eq!(state, State::Initialized(data));
|
assert_eq!(state, State::Initialized(data));
|
||||||
|
@ -448,8 +468,8 @@ mod test {
|
||||||
.convert_to_current();
|
.convert_to_current();
|
||||||
let data = nonce::state::Data::new(
|
let data = nonce::state::Data::new(
|
||||||
authority,
|
authority,
|
||||||
*invoke_context.get_blockhash(),
|
invoke_context.blockhash,
|
||||||
invoke_context.get_lamports_per_signature(),
|
invoke_context.lamports_per_signature,
|
||||||
);
|
);
|
||||||
assert_eq!(state, State::Initialized(data));
|
assert_eq!(state, State::Initialized(data));
|
||||||
let signers = HashSet::new();
|
let signers = HashSet::new();
|
||||||
|
@ -726,8 +746,8 @@ mod test {
|
||||||
.convert_to_current();
|
.convert_to_current();
|
||||||
let data = nonce::state::Data::new(
|
let data = nonce::state::Data::new(
|
||||||
authority,
|
authority,
|
||||||
*invoke_context.get_blockhash(),
|
invoke_context.blockhash,
|
||||||
invoke_context.get_lamports_per_signature(),
|
invoke_context.lamports_per_signature,
|
||||||
);
|
);
|
||||||
assert_eq!(state, State::Initialized(data.clone()));
|
assert_eq!(state, State::Initialized(data.clone()));
|
||||||
with_test_keyed_account(42, false, |to_keyed| {
|
with_test_keyed_account(42, false, |to_keyed| {
|
||||||
|
@ -749,8 +769,8 @@ mod test {
|
||||||
.convert_to_current();
|
.convert_to_current();
|
||||||
let data = nonce::state::Data::new(
|
let data = nonce::state::Data::new(
|
||||||
data.authority,
|
data.authority,
|
||||||
*invoke_context.get_blockhash(),
|
invoke_context.blockhash,
|
||||||
invoke_context.get_lamports_per_signature(),
|
invoke_context.lamports_per_signature,
|
||||||
);
|
);
|
||||||
assert_eq!(state, State::Initialized(data));
|
assert_eq!(state, State::Initialized(data));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
@ -923,8 +943,8 @@ mod test {
|
||||||
let result = keyed_account.initialize_nonce_account(&authority, &rent, &invoke_context);
|
let result = keyed_account.initialize_nonce_account(&authority, &rent, &invoke_context);
|
||||||
let data = nonce::state::Data::new(
|
let data = nonce::state::Data::new(
|
||||||
authority,
|
authority,
|
||||||
*invoke_context.get_blockhash(),
|
invoke_context.blockhash,
|
||||||
invoke_context.get_lamports_per_signature(),
|
invoke_context.lamports_per_signature,
|
||||||
);
|
);
|
||||||
assert_eq!(result, Ok(()));
|
assert_eq!(result, Ok(()));
|
||||||
let state = AccountUtilsState::<Versions>::state(keyed_account)
|
let state = AccountUtilsState::<Versions>::state(keyed_account)
|
||||||
|
@ -988,8 +1008,8 @@ mod test {
|
||||||
let authority = Pubkey::default();
|
let authority = Pubkey::default();
|
||||||
let data = nonce::state::Data::new(
|
let data = nonce::state::Data::new(
|
||||||
authority,
|
authority,
|
||||||
*invoke_context.get_blockhash(),
|
invoke_context.blockhash,
|
||||||
invoke_context.get_lamports_per_signature(),
|
invoke_context.lamports_per_signature,
|
||||||
);
|
);
|
||||||
let result = nonce_account.authorize_nonce_account(
|
let result = nonce_account.authorize_nonce_account(
|
||||||
&Pubkey::default(),
|
&Pubkey::default(),
|
||||||
|
@ -1062,7 +1082,7 @@ mod test {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert!(verify_nonce_account(
|
assert!(verify_nonce_account(
|
||||||
&nonce_account.account.borrow(),
|
&nonce_account.account.borrow(),
|
||||||
invoke_context.get_blockhash(),
|
&invoke_context.blockhash,
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -1093,7 +1113,7 @@ mod test {
|
||||||
let invoke_context = create_invoke_context_with_blockhash(1);
|
let invoke_context = create_invoke_context_with_blockhash(1);
|
||||||
assert!(!verify_nonce_account(
|
assert!(!verify_nonce_account(
|
||||||
&nonce_account.account.borrow(),
|
&nonce_account.account.borrow(),
|
||||||
invoke_context.get_blockhash(),
|
&invoke_context.blockhash,
|
||||||
));
|
));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,9 @@ fn assign(
|
||||||
// Thus, we're starting to remove this restriction from system instruction
|
// Thus, we're starting to remove this restriction from system instruction
|
||||||
// processor for consistency and fewer special casing by piggybacking onto
|
// processor for consistency and fewer special casing by piggybacking onto
|
||||||
// the related feature gate..
|
// the related feature gate..
|
||||||
let rent_for_sysvars = invoke_context.is_feature_active(&feature_set::rent_for_sysvars::id());
|
let rent_for_sysvars = invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&feature_set::rent_for_sysvars::id());
|
||||||
if !rent_for_sysvars && sysvar::check_id(owner) {
|
if !rent_for_sysvars && sysvar::check_id(owner) {
|
||||||
// guard against sysvars being made
|
// guard against sysvars being made
|
||||||
ic_msg!(invoke_context, "Assign: cannot assign to sysvar, {}", owner);
|
ic_msg!(invoke_context, "Assign: cannot assign to sysvar, {}", owner);
|
||||||
|
@ -205,7 +207,9 @@ fn transfer(
|
||||||
lamports: u64,
|
lamports: u64,
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
if !invoke_context.is_feature_active(&feature_set::system_transfer_zero_check::id())
|
if !invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&feature_set::system_transfer_zero_check::id())
|
||||||
&& lamports == 0
|
&& lamports == 0
|
||||||
{
|
{
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -232,7 +236,9 @@ fn transfer_with_seed(
|
||||||
lamports: u64,
|
lamports: u64,
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
if !invoke_context.is_feature_active(&feature_set::system_transfer_zero_check::id())
|
if !invoke_context
|
||||||
|
.feature_set
|
||||||
|
.is_active(&feature_set::system_transfer_zero_check::id())
|
||||||
&& lamports == 0
|
&& lamports == 0
|
||||||
{
|
{
|
||||||
return Ok(());
|
return Ok(());
|
||||||
|
@ -944,8 +950,8 @@ mod tests {
|
||||||
feature_set
|
feature_set
|
||||||
.inactive
|
.inactive
|
||||||
.insert(feature_set::rent_for_sysvars::id());
|
.insert(feature_set::rent_for_sysvars::id());
|
||||||
let invoke_context =
|
let mut invoke_context = InvokeContext::new_mock(&[], &[]);
|
||||||
InvokeContext::new_mock_with_sysvars_and_features(&[], &[], &[], Arc::new(feature_set));
|
invoke_context.feature_set = Arc::new(feature_set);
|
||||||
// Attempt to create system account in account already owned by another program
|
// Attempt to create system account in account already owned by another program
|
||||||
let from = Pubkey::new_unique();
|
let from = Pubkey::new_unique();
|
||||||
let from_account = AccountSharedData::new_ref(100, 0, &system_program::id());
|
let from_account = AccountSharedData::new_ref(100, 0, &system_program::id());
|
||||||
|
@ -1107,8 +1113,8 @@ mod tests {
|
||||||
feature_set
|
feature_set
|
||||||
.inactive
|
.inactive
|
||||||
.insert(feature_set::rent_for_sysvars::id());
|
.insert(feature_set::rent_for_sysvars::id());
|
||||||
let invoke_context =
|
let mut invoke_context = InvokeContext::new_mock(&[], &[]);
|
||||||
InvokeContext::new_mock_with_sysvars_and_features(&[], &[], &[], Arc::new(feature_set));
|
invoke_context.feature_set = Arc::new(feature_set);
|
||||||
let new_owner = sysvar::id();
|
let new_owner = sysvar::id();
|
||||||
let from = Pubkey::new_unique();
|
let from = Pubkey::new_unique();
|
||||||
let mut from_account = AccountSharedData::new(100, 0, &system_program::id());
|
let mut from_account = AccountSharedData::new(100, 0, &system_program::id());
|
||||||
|
@ -1575,7 +1581,7 @@ mod tests {
|
||||||
|first_instruction_account: usize,
|
|first_instruction_account: usize,
|
||||||
instruction_data: &[u8],
|
instruction_data: &[u8],
|
||||||
invoke_context: &mut InvokeContext| {
|
invoke_context: &mut InvokeContext| {
|
||||||
invoke_context.set_blockhash(hash(&serialize(&0).unwrap()));
|
invoke_context.blockhash = hash(&serialize(&0).unwrap());
|
||||||
super::process_instruction(
|
super::process_instruction(
|
||||||
first_instruction_account,
|
first_instruction_account,
|
||||||
instruction_data,
|
instruction_data,
|
||||||
|
@ -1991,7 +1997,7 @@ mod tests {
|
||||||
|first_instruction_account: usize,
|
|first_instruction_account: usize,
|
||||||
instruction_data: &[u8],
|
instruction_data: &[u8],
|
||||||
invoke_context: &mut InvokeContext| {
|
invoke_context: &mut InvokeContext| {
|
||||||
invoke_context.set_blockhash(hash(&serialize(&0).unwrap()));
|
invoke_context.blockhash = hash(&serialize(&0).unwrap());
|
||||||
super::process_instruction(
|
super::process_instruction(
|
||||||
first_instruction_account,
|
first_instruction_account,
|
||||||
instruction_data,
|
instruction_data,
|
||||||
|
|
Loading…
Reference in New Issue