Refactor: instruction account index (#25825)
* Adds methods based on instruction_account_index to InstructionContext. Removes methods which are based on index_in_instruction. * Adjusts program-runtime. * Adjusts runtime. * Adjusts bpf loader. * Adjusts built-in programs. * Adjusts program-test and bpf tests.
This commit is contained in:
parent
8e3fd8a411
commit
bf9ca9827e
|
@ -368,10 +368,10 @@ impl<'a> InvokeContext<'a> {
|
||||||
|
|
||||||
self.pre_accounts = Vec::with_capacity(instruction_accounts.len());
|
self.pre_accounts = Vec::with_capacity(instruction_accounts.len());
|
||||||
|
|
||||||
for (index_in_instruction, instruction_account) in
|
for (instruction_account_index, instruction_account) in
|
||||||
instruction_accounts.iter().enumerate()
|
instruction_accounts.iter().enumerate()
|
||||||
{
|
{
|
||||||
if index_in_instruction != instruction_account.index_in_callee {
|
if instruction_account_index != instruction_account.index_in_callee {
|
||||||
continue; // Skip duplicate account
|
continue; // Skip duplicate account
|
||||||
}
|
}
|
||||||
if instruction_account.index_in_transaction
|
if instruction_account.index_in_transaction
|
||||||
|
@ -398,7 +398,8 @@ impl<'a> InvokeContext<'a> {
|
||||||
self.transaction_context
|
self.transaction_context
|
||||||
.get_instruction_context_at(level)
|
.get_instruction_context_at(level)
|
||||||
.and_then(|instruction_context| {
|
.and_then(|instruction_context| {
|
||||||
instruction_context.try_borrow_program_account(self.transaction_context)
|
instruction_context
|
||||||
|
.try_borrow_last_program_account(self.transaction_context)
|
||||||
})
|
})
|
||||||
.map(|program_account| program_account.get_key() == program_id)
|
.map(|program_account| program_account.get_key() == program_id)
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
|
@ -407,7 +408,7 @@ impl<'a> InvokeContext<'a> {
|
||||||
.transaction_context
|
.transaction_context
|
||||||
.get_current_instruction_context()
|
.get_current_instruction_context()
|
||||||
.and_then(|instruction_context| {
|
.and_then(|instruction_context| {
|
||||||
instruction_context.try_borrow_program_account(self.transaction_context)
|
instruction_context.try_borrow_last_program_account(self.transaction_context)
|
||||||
})
|
})
|
||||||
.map(|program_account| program_account.get_key() == program_id)
|
.map(|program_account| program_account.get_key() == program_id)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
@ -490,7 +491,7 @@ impl<'a> InvokeContext<'a> {
|
||||||
.get_current_instruction_context()
|
.get_current_instruction_context()
|
||||||
.map_err(|_| InstructionError::CallDepth)?;
|
.map_err(|_| InstructionError::CallDepth)?;
|
||||||
let program_id = instruction_context
|
let program_id = instruction_context
|
||||||
.get_program_key(self.transaction_context)
|
.get_last_program_key(self.transaction_context)
|
||||||
.map_err(|_| InstructionError::CallDepth)?;
|
.map_err(|_| InstructionError::CallDepth)?;
|
||||||
|
|
||||||
// Verify all executable accounts have zero outstanding refs
|
// Verify all executable accounts have zero outstanding refs
|
||||||
|
@ -504,8 +505,10 @@ impl<'a> InvokeContext<'a> {
|
||||||
// Verify the per-account instruction results
|
// Verify the per-account instruction results
|
||||||
let (mut pre_sum, mut post_sum) = (0_u128, 0_u128);
|
let (mut pre_sum, mut post_sum) = (0_u128, 0_u128);
|
||||||
let mut pre_account_index = 0;
|
let mut pre_account_index = 0;
|
||||||
for (index_in_instruction, instruction_account) in instruction_accounts.iter().enumerate() {
|
for (instruction_account_index, instruction_account) in
|
||||||
if index_in_instruction != instruction_account.index_in_callee {
|
instruction_accounts.iter().enumerate()
|
||||||
|
{
|
||||||
|
if instruction_account_index != instruction_account.index_in_callee {
|
||||||
continue; // Skip duplicate account
|
continue; // Skip duplicate account
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -581,13 +584,15 @@ impl<'a> InvokeContext<'a> {
|
||||||
let transaction_context = &self.transaction_context;
|
let transaction_context = &self.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
let program_id = instruction_context
|
let program_id = instruction_context
|
||||||
.get_program_key(transaction_context)
|
.get_last_program_key(transaction_context)
|
||||||
.map_err(|_| InstructionError::CallDepth)?;
|
.map_err(|_| InstructionError::CallDepth)?;
|
||||||
|
|
||||||
// Verify the per-account instruction results
|
// Verify the per-account instruction results
|
||||||
let (mut pre_sum, mut post_sum) = (0_u128, 0_u128);
|
let (mut pre_sum, mut post_sum) = (0_u128, 0_u128);
|
||||||
for (index_in_instruction, instruction_account) in instruction_accounts.iter().enumerate() {
|
for (instruction_account_index, instruction_account) in
|
||||||
if index_in_instruction != instruction_account.index_in_callee {
|
instruction_accounts.iter().enumerate()
|
||||||
|
{
|
||||||
|
if instruction_account_index != instruction_account.index_in_callee {
|
||||||
continue; // Skip duplicate account
|
continue; // Skip duplicate account
|
||||||
}
|
}
|
||||||
if instruction_account.index_in_transaction
|
if instruction_account.index_in_transaction
|
||||||
|
@ -599,11 +604,7 @@ impl<'a> InvokeContext<'a> {
|
||||||
.get_account_at_index(instruction_account.index_in_transaction)?;
|
.get_account_at_index(instruction_account.index_in_transaction)?;
|
||||||
let is_writable = if before_instruction_context_push {
|
let is_writable = if before_instruction_context_push {
|
||||||
instruction_context
|
instruction_context
|
||||||
.try_borrow_instruction_account(
|
.is_instruction_account_writable(instruction_account.index_in_caller)?
|
||||||
self.transaction_context,
|
|
||||||
instruction_account.index_in_caller,
|
|
||||||
)?
|
|
||||||
.is_writable()
|
|
||||||
} else {
|
} else {
|
||||||
instruction_account.is_writable
|
instruction_account.is_writable
|
||||||
};
|
};
|
||||||
|
@ -713,7 +714,7 @@ impl<'a> InvokeContext<'a> {
|
||||||
let instruction_context = self.transaction_context.get_current_instruction_context()?;
|
let instruction_context = self.transaction_context.get_current_instruction_context()?;
|
||||||
let mut deduplicated_instruction_accounts: Vec<InstructionAccount> = Vec::new();
|
let mut deduplicated_instruction_accounts: Vec<InstructionAccount> = Vec::new();
|
||||||
let mut duplicate_indicies = Vec::with_capacity(instruction.accounts.len());
|
let mut duplicate_indicies = Vec::with_capacity(instruction.accounts.len());
|
||||||
for (index_in_instruction, account_meta) in instruction.accounts.iter().enumerate() {
|
for (instruction_account_index, account_meta) in instruction.accounts.iter().enumerate() {
|
||||||
let index_in_transaction = self
|
let index_in_transaction = self
|
||||||
.transaction_context
|
.transaction_context
|
||||||
.find_index_of_account(&account_meta.pubkey)
|
.find_index_of_account(&account_meta.pubkey)
|
||||||
|
@ -740,10 +741,10 @@ impl<'a> InvokeContext<'a> {
|
||||||
instruction_account.is_writable |= account_meta.is_writable;
|
instruction_account.is_writable |= account_meta.is_writable;
|
||||||
} else {
|
} else {
|
||||||
let index_in_caller = instruction_context
|
let index_in_caller = instruction_context
|
||||||
.find_index_of_account(self.transaction_context, &account_meta.pubkey)
|
.find_index_of_instruction_account(
|
||||||
.map(|index| {
|
self.transaction_context,
|
||||||
index.saturating_sub(instruction_context.get_number_of_program_accounts())
|
&account_meta.pubkey,
|
||||||
})
|
)
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
ic_msg!(
|
ic_msg!(
|
||||||
self,
|
self,
|
||||||
|
@ -756,7 +757,7 @@ impl<'a> InvokeContext<'a> {
|
||||||
deduplicated_instruction_accounts.push(InstructionAccount {
|
deduplicated_instruction_accounts.push(InstructionAccount {
|
||||||
index_in_transaction,
|
index_in_transaction,
|
||||||
index_in_caller,
|
index_in_caller,
|
||||||
index_in_callee: index_in_instruction,
|
index_in_callee: instruction_account_index,
|
||||||
is_signer: account_meta.is_signer,
|
is_signer: account_meta.is_signer,
|
||||||
is_writable: account_meta.is_writable,
|
is_writable: account_meta.is_writable,
|
||||||
});
|
});
|
||||||
|
@ -804,13 +805,13 @@ impl<'a> InvokeContext<'a> {
|
||||||
// Find and validate executables / program accounts
|
// Find and validate executables / program accounts
|
||||||
let callee_program_id = instruction.program_id;
|
let callee_program_id = instruction.program_id;
|
||||||
let program_account_index = instruction_context
|
let program_account_index = instruction_context
|
||||||
.find_index_of_account(self.transaction_context, &callee_program_id)
|
.find_index_of_instruction_account(self.transaction_context, &callee_program_id)
|
||||||
.ok_or_else(|| {
|
.ok_or_else(|| {
|
||||||
ic_msg!(self, "Unknown program {}", callee_program_id);
|
ic_msg!(self, "Unknown program {}", callee_program_id);
|
||||||
InstructionError::MissingAccount
|
InstructionError::MissingAccount
|
||||||
})?;
|
})?;
|
||||||
let borrowed_program_account = instruction_context
|
let borrowed_program_account = instruction_context
|
||||||
.try_borrow_account(self.transaction_context, program_account_index)?;
|
.try_borrow_instruction_account(self.transaction_context, program_account_index)?;
|
||||||
if !borrowed_program_account.is_executable() {
|
if !borrowed_program_account.is_executable() {
|
||||||
ic_msg!(self, "Account {} is not executable", callee_program_id);
|
ic_msg!(self, "Account {} is not executable", callee_program_id);
|
||||||
return Err(InstructionError::AccountNotExecutable);
|
return Err(InstructionError::AccountNotExecutable);
|
||||||
|
@ -952,7 +953,7 @@ impl<'a> InvokeContext<'a> {
|
||||||
|
|
||||||
let (first_instruction_account, builtin_id) = {
|
let (first_instruction_account, builtin_id) = {
|
||||||
let borrowed_root_account = instruction_context
|
let borrowed_root_account = instruction_context
|
||||||
.try_borrow_account(self.transaction_context, 0)
|
.try_borrow_program_account(self.transaction_context, 0)
|
||||||
.map_err(|_| InstructionError::UnsupportedProgramId)?;
|
.map_err(|_| InstructionError::UnsupportedProgramId)?;
|
||||||
let owner_id = borrowed_root_account.get_owner();
|
let owner_id = borrowed_root_account.get_owner();
|
||||||
if solana_sdk::native_loader::check_id(owner_id) {
|
if solana_sdk::native_loader::check_id(owner_id) {
|
||||||
|
@ -964,7 +965,8 @@ impl<'a> InvokeContext<'a> {
|
||||||
|
|
||||||
for entry in self.builtin_programs {
|
for entry in self.builtin_programs {
|
||||||
if entry.program_id == builtin_id {
|
if entry.program_id == builtin_id {
|
||||||
let program_id = instruction_context.get_program_id(self.transaction_context);
|
let program_id =
|
||||||
|
*instruction_context.get_last_program_key(self.transaction_context)?;
|
||||||
if builtin_id == program_id {
|
if builtin_id == program_id {
|
||||||
let logger = self.get_log_collector();
|
let logger = self.get_log_collector();
|
||||||
stable_log::program_invoke(&logger, &program_id, self.get_stack_height());
|
stable_log::program_invoke(&logger, &program_id, self.get_stack_height());
|
||||||
|
@ -1123,19 +1125,19 @@ pub fn prepare_mock_invoke_context(
|
||||||
) -> MockInvokeContextPreparation {
|
) -> MockInvokeContextPreparation {
|
||||||
let mut instruction_accounts: Vec<InstructionAccount> =
|
let mut instruction_accounts: Vec<InstructionAccount> =
|
||||||
Vec::with_capacity(instruction_account_metas.len());
|
Vec::with_capacity(instruction_account_metas.len());
|
||||||
for (index_in_instruction, account_meta) in instruction_account_metas.iter().enumerate() {
|
for (instruction_account_index, account_meta) in instruction_account_metas.iter().enumerate() {
|
||||||
let index_in_transaction = transaction_accounts
|
let index_in_transaction = transaction_accounts
|
||||||
.iter()
|
.iter()
|
||||||
.position(|(key, _account)| *key == account_meta.pubkey)
|
.position(|(key, _account)| *key == account_meta.pubkey)
|
||||||
.unwrap_or(transaction_accounts.len());
|
.unwrap_or(transaction_accounts.len());
|
||||||
let index_in_callee = instruction_accounts
|
let index_in_callee = instruction_accounts
|
||||||
.get(0..index_in_instruction)
|
.get(0..instruction_account_index)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.iter()
|
.iter()
|
||||||
.position(|instruction_account| {
|
.position(|instruction_account| {
|
||||||
instruction_account.index_in_transaction == index_in_transaction
|
instruction_account.index_in_transaction == index_in_transaction
|
||||||
})
|
})
|
||||||
.unwrap_or(index_in_instruction);
|
.unwrap_or(instruction_account_index);
|
||||||
instruction_accounts.push(InstructionAccount {
|
instruction_accounts.push(InstructionAccount {
|
||||||
index_in_transaction,
|
index_in_transaction,
|
||||||
index_in_caller: index_in_transaction,
|
index_in_caller: index_in_transaction,
|
||||||
|
@ -1295,7 +1297,7 @@ mod tests {
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
let instruction_data = instruction_context.get_instruction_data();
|
let instruction_data = instruction_context.get_instruction_data();
|
||||||
let program_id = instruction_context.get_program_key(transaction_context)?;
|
let program_id = instruction_context.get_last_program_key(transaction_context)?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
program_id,
|
program_id,
|
||||||
instruction_context
|
instruction_context
|
||||||
|
@ -1528,12 +1530,12 @@ mod tests {
|
||||||
AccountMeta::new_readonly(accounts.get(2).unwrap().0, false),
|
AccountMeta::new_readonly(accounts.get(2).unwrap().0, false),
|
||||||
];
|
];
|
||||||
let instruction_accounts = (0..4)
|
let instruction_accounts = (0..4)
|
||||||
.map(|index_in_instruction| InstructionAccount {
|
.map(|instruction_account_index| InstructionAccount {
|
||||||
index_in_transaction: index_in_instruction,
|
index_in_transaction: instruction_account_index,
|
||||||
index_in_caller: index_in_instruction,
|
index_in_caller: instruction_account_index,
|
||||||
index_in_callee: index_in_instruction,
|
index_in_callee: instruction_account_index,
|
||||||
is_signer: false,
|
is_signer: false,
|
||||||
is_writable: index_in_instruction < 2,
|
is_writable: instruction_account_index < 2,
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
let mut transaction_context = TransactionContext::new(accounts, 2, 8);
|
let mut transaction_context = TransactionContext::new(accounts, 2, 8);
|
||||||
|
|
|
@ -186,10 +186,9 @@ pub mod get_sysvar_with_account_check {
|
||||||
instruction_context: &InstructionContext,
|
instruction_context: &InstructionContext,
|
||||||
instruction_account_index: usize,
|
instruction_account_index: usize,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
if !S::check_id(
|
let index_in_transaction = instruction_context
|
||||||
instruction_context
|
.get_index_of_instruction_account_in_transaction(instruction_account_index)?;
|
||||||
.get_instruction_account_key(transaction_context, instruction_account_index)?,
|
if !S::check_id(transaction_context.get_key_of_account_at_index(index_in_transaction)?) {
|
||||||
) {
|
|
||||||
return Err(InstructionError::InvalidArgument);
|
return Err(InstructionError::InvalidArgument);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -198,12 +197,12 @@ pub mod get_sysvar_with_account_check {
|
||||||
pub fn clock(
|
pub fn clock(
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
instruction_context: &InstructionContext,
|
instruction_context: &InstructionContext,
|
||||||
index_in_instruction: usize,
|
instruction_account_index: usize,
|
||||||
) -> Result<Arc<Clock>, InstructionError> {
|
) -> Result<Arc<Clock>, InstructionError> {
|
||||||
check_sysvar_account::<Clock>(
|
check_sysvar_account::<Clock>(
|
||||||
invoke_context.transaction_context,
|
invoke_context.transaction_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
index_in_instruction,
|
instruction_account_index,
|
||||||
)?;
|
)?;
|
||||||
invoke_context.get_sysvar_cache().get_clock()
|
invoke_context.get_sysvar_cache().get_clock()
|
||||||
}
|
}
|
||||||
|
@ -211,12 +210,12 @@ pub mod get_sysvar_with_account_check {
|
||||||
pub fn rent(
|
pub fn rent(
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
instruction_context: &InstructionContext,
|
instruction_context: &InstructionContext,
|
||||||
index_in_instruction: usize,
|
instruction_account_index: usize,
|
||||||
) -> Result<Arc<Rent>, InstructionError> {
|
) -> Result<Arc<Rent>, InstructionError> {
|
||||||
check_sysvar_account::<Rent>(
|
check_sysvar_account::<Rent>(
|
||||||
invoke_context.transaction_context,
|
invoke_context.transaction_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
index_in_instruction,
|
instruction_account_index,
|
||||||
)?;
|
)?;
|
||||||
invoke_context.get_sysvar_cache().get_rent()
|
invoke_context.get_sysvar_cache().get_rent()
|
||||||
}
|
}
|
||||||
|
@ -224,12 +223,12 @@ pub mod get_sysvar_with_account_check {
|
||||||
pub fn slot_hashes(
|
pub fn slot_hashes(
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
instruction_context: &InstructionContext,
|
instruction_context: &InstructionContext,
|
||||||
index_in_instruction: usize,
|
instruction_account_index: usize,
|
||||||
) -> Result<Arc<SlotHashes>, InstructionError> {
|
) -> Result<Arc<SlotHashes>, InstructionError> {
|
||||||
check_sysvar_account::<SlotHashes>(
|
check_sysvar_account::<SlotHashes>(
|
||||||
invoke_context.transaction_context,
|
invoke_context.transaction_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
index_in_instruction,
|
instruction_account_index,
|
||||||
)?;
|
)?;
|
||||||
invoke_context.get_sysvar_cache().get_slot_hashes()
|
invoke_context.get_sysvar_cache().get_slot_hashes()
|
||||||
}
|
}
|
||||||
|
@ -238,12 +237,12 @@ pub mod get_sysvar_with_account_check {
|
||||||
pub fn recent_blockhashes(
|
pub fn recent_blockhashes(
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
instruction_context: &InstructionContext,
|
instruction_context: &InstructionContext,
|
||||||
index_in_instruction: usize,
|
instruction_account_index: usize,
|
||||||
) -> Result<Arc<RecentBlockhashes>, InstructionError> {
|
) -> Result<Arc<RecentBlockhashes>, InstructionError> {
|
||||||
check_sysvar_account::<RecentBlockhashes>(
|
check_sysvar_account::<RecentBlockhashes>(
|
||||||
invoke_context.transaction_context,
|
invoke_context.transaction_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
index_in_instruction,
|
instruction_account_index,
|
||||||
)?;
|
)?;
|
||||||
invoke_context.get_sysvar_cache().get_recent_blockhashes()
|
invoke_context.get_sysvar_cache().get_recent_blockhashes()
|
||||||
}
|
}
|
||||||
|
@ -251,12 +250,12 @@ pub mod get_sysvar_with_account_check {
|
||||||
pub fn stake_history(
|
pub fn stake_history(
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
instruction_context: &InstructionContext,
|
instruction_context: &InstructionContext,
|
||||||
index_in_instruction: usize,
|
instruction_account_index: usize,
|
||||||
) -> Result<Arc<StakeHistory>, InstructionError> {
|
) -> Result<Arc<StakeHistory>, InstructionError> {
|
||||||
check_sysvar_account::<StakeHistory>(
|
check_sysvar_account::<StakeHistory>(
|
||||||
invoke_context.transaction_context,
|
invoke_context.transaction_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
index_in_instruction,
|
instruction_account_index,
|
||||||
)?;
|
)?;
|
||||||
invoke_context.get_sysvar_cache().get_stake_history()
|
invoke_context.get_sysvar_cache().get_stake_history()
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,11 +101,10 @@ pub fn builtin_process_instruction(
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
let instruction_data = instruction_context.get_instruction_data();
|
let instruction_data = instruction_context.get_instruction_data();
|
||||||
let indices_in_instruction = instruction_context.get_number_of_program_accounts()
|
let instruction_account_indices = 0..instruction_context.get_number_of_instruction_accounts();
|
||||||
..instruction_context.get_number_of_accounts();
|
|
||||||
|
|
||||||
let log_collector = invoke_context.get_log_collector();
|
let log_collector = invoke_context.get_log_collector();
|
||||||
let program_id = instruction_context.get_program_key(transaction_context)?;
|
let program_id = instruction_context.get_last_program_key(transaction_context)?;
|
||||||
stable_log::program_invoke(
|
stable_log::program_invoke(
|
||||||
&log_collector,
|
&log_collector,
|
||||||
program_id,
|
program_id,
|
||||||
|
@ -113,14 +112,14 @@ pub fn builtin_process_instruction(
|
||||||
);
|
);
|
||||||
|
|
||||||
// Copy indices_in_instruction into a HashSet to ensure there are no duplicates
|
// Copy indices_in_instruction into a HashSet to ensure there are no duplicates
|
||||||
let deduplicated_indices: HashSet<usize> = indices_in_instruction.clone().collect();
|
let deduplicated_indices: HashSet<usize> = instruction_account_indices.clone().collect();
|
||||||
|
|
||||||
// Create copies of the accounts
|
// Create copies of the accounts
|
||||||
let mut account_copies = deduplicated_indices
|
let mut account_copies = deduplicated_indices
|
||||||
.iter()
|
.iter()
|
||||||
.map(|index_in_instruction| {
|
.map(|instruction_account_index| {
|
||||||
let borrowed_account = instruction_context
|
let borrowed_account = instruction_context
|
||||||
.try_borrow_account(transaction_context, *index_in_instruction)?;
|
.try_borrow_instruction_account(transaction_context, *instruction_account_index)?;
|
||||||
Ok((
|
Ok((
|
||||||
*borrowed_account.get_key(),
|
*borrowed_account.get_key(),
|
||||||
*borrowed_account.get_owner(),
|
*borrowed_account.get_owner(),
|
||||||
|
@ -144,15 +143,15 @@ pub fn builtin_process_instruction(
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
// Create AccountInfos
|
// Create AccountInfos
|
||||||
let account_infos = indices_in_instruction
|
let account_infos = instruction_account_indices
|
||||||
.map(|index_in_instruction| {
|
.map(|instruction_account_index| {
|
||||||
let account_copy_index = deduplicated_indices
|
let account_copy_index = deduplicated_indices
|
||||||
.iter()
|
.iter()
|
||||||
.position(|index| *index == index_in_instruction)
|
.position(|index| *index == instruction_account_index)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let (key, owner, lamports, data) = &account_refs[account_copy_index];
|
let (key, owner, lamports, data) = &account_refs[account_copy_index];
|
||||||
let borrowed_account = instruction_context
|
let borrowed_account = instruction_context
|
||||||
.try_borrow_account(transaction_context, index_in_instruction)?;
|
.try_borrow_instruction_account(transaction_context, instruction_account_index)?;
|
||||||
Ok(AccountInfo {
|
Ok(AccountInfo {
|
||||||
key,
|
key,
|
||||||
is_signer: borrowed_account.is_signer(),
|
is_signer: borrowed_account.is_signer(),
|
||||||
|
@ -175,12 +174,12 @@ pub fn builtin_process_instruction(
|
||||||
stable_log::program_success(&log_collector, program_id);
|
stable_log::program_success(&log_collector, program_id);
|
||||||
|
|
||||||
// Commit AccountInfo changes back into KeyedAccounts
|
// Commit AccountInfo changes back into KeyedAccounts
|
||||||
for (index_in_instruction, (_key, _owner, lamports, data)) in deduplicated_indices
|
for (instruction_account_index, (_key, _owner, lamports, data)) in deduplicated_indices
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(account_copies.into_iter())
|
.zip(account_copies.into_iter())
|
||||||
{
|
{
|
||||||
let mut borrowed_account =
|
let mut borrowed_account = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, index_in_instruction)?;
|
.try_borrow_instruction_account(transaction_context, instruction_account_index)?;
|
||||||
if borrowed_account.is_writable() {
|
if borrowed_account.is_writable() {
|
||||||
borrowed_account.set_lamports(lamports)?;
|
borrowed_account.set_lamports(lamports)?;
|
||||||
borrowed_account.set_data(&data)?;
|
borrowed_account.set_data(&data)?;
|
||||||
|
@ -253,7 +252,7 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
|
||||||
.get_current_instruction_context()
|
.get_current_instruction_context()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let caller = instruction_context
|
let caller = instruction_context
|
||||||
.get_program_key(transaction_context)
|
.get_last_program_key(transaction_context)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
stable_log::program_invoke(
|
stable_log::program_invoke(
|
||||||
|
@ -379,7 +378,7 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
|
||||||
.get_current_instruction_context()
|
.get_current_instruction_context()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let caller = *instruction_context
|
let caller = *instruction_context
|
||||||
.get_program_key(transaction_context)
|
.get_last_program_key(transaction_context)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
transaction_context
|
transaction_context
|
||||||
.set_return_data(caller, data.to_vec())
|
.set_return_data(caller, data.to_vec())
|
||||||
|
|
|
@ -18,7 +18,7 @@ use {
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn process_instruction(
|
pub fn process_instruction(
|
||||||
first_instruction_account: usize,
|
_first_instruction_account: usize,
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
|
@ -28,24 +28,15 @@ pub fn process_instruction(
|
||||||
ProgramInstruction::CreateLookupTable {
|
ProgramInstruction::CreateLookupTable {
|
||||||
recent_slot,
|
recent_slot,
|
||||||
bump_seed,
|
bump_seed,
|
||||||
} => Processor::create_lookup_table(
|
} => Processor::create_lookup_table(invoke_context, recent_slot, bump_seed),
|
||||||
invoke_context,
|
ProgramInstruction::FreezeLookupTable => Processor::freeze_lookup_table(invoke_context),
|
||||||
first_instruction_account,
|
|
||||||
recent_slot,
|
|
||||||
bump_seed,
|
|
||||||
),
|
|
||||||
ProgramInstruction::FreezeLookupTable => {
|
|
||||||
Processor::freeze_lookup_table(invoke_context, first_instruction_account)
|
|
||||||
}
|
|
||||||
ProgramInstruction::ExtendLookupTable { new_addresses } => {
|
ProgramInstruction::ExtendLookupTable { new_addresses } => {
|
||||||
Processor::extend_lookup_table(invoke_context, first_instruction_account, new_addresses)
|
Processor::extend_lookup_table(invoke_context, new_addresses)
|
||||||
}
|
}
|
||||||
ProgramInstruction::DeactivateLookupTable => {
|
ProgramInstruction::DeactivateLookupTable => {
|
||||||
Processor::deactivate_lookup_table(invoke_context, first_instruction_account)
|
Processor::deactivate_lookup_table(invoke_context)
|
||||||
}
|
|
||||||
ProgramInstruction::CloseLookupTable => {
|
|
||||||
Processor::close_lookup_table(invoke_context, first_instruction_account)
|
|
||||||
}
|
}
|
||||||
|
ProgramInstruction::CloseLookupTable => Processor::close_lookup_table(invoke_context),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,7 +48,6 @@ pub struct Processor;
|
||||||
impl Processor {
|
impl Processor {
|
||||||
fn create_lookup_table(
|
fn create_lookup_table(
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
_first_instruction_account: usize,
|
|
||||||
untrusted_recent_slot: Slot,
|
untrusted_recent_slot: Slot,
|
||||||
bump_seed: u8,
|
bump_seed: u8,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
|
@ -161,10 +151,7 @@ impl Processor {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn freeze_lookup_table(
|
fn freeze_lookup_table(invoke_context: &mut InvokeContext) -> Result<(), InstructionError> {
|
||||||
invoke_context: &mut InvokeContext,
|
|
||||||
_first_instruction_account: usize,
|
|
||||||
) -> Result<(), InstructionError> {
|
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
|
|
||||||
|
@ -217,7 +204,6 @@ impl Processor {
|
||||||
|
|
||||||
fn extend_lookup_table(
|
fn extend_lookup_table(
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
_first_instruction_account: usize,
|
|
||||||
new_addresses: Vec<Pubkey>,
|
new_addresses: Vec<Pubkey>,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
|
@ -335,10 +321,7 @@ impl Processor {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deactivate_lookup_table(
|
fn deactivate_lookup_table(invoke_context: &mut InvokeContext) -> Result<(), InstructionError> {
|
||||||
invoke_context: &mut InvokeContext,
|
|
||||||
_first_instruction_account: usize,
|
|
||||||
) -> Result<(), InstructionError> {
|
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
|
|
||||||
|
@ -387,10 +370,7 @@ impl Processor {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn close_lookup_table(
|
fn close_lookup_table(invoke_context: &mut InvokeContext) -> Result<(), InstructionError> {
|
||||||
invoke_context: &mut InvokeContext,
|
|
||||||
_first_instruction_account: usize,
|
|
||||||
) -> Result<(), InstructionError> {
|
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
|
|
||||||
|
@ -411,13 +391,8 @@ impl Processor {
|
||||||
drop(authority_account);
|
drop(authority_account);
|
||||||
|
|
||||||
instruction_context.check_number_of_instruction_accounts(3)?;
|
instruction_context.check_number_of_instruction_accounts(3)?;
|
||||||
if instruction_context
|
if instruction_context.get_index_of_instruction_account_in_transaction(0)?
|
||||||
.get_index_in_transaction(instruction_context.get_number_of_program_accounts())?
|
== instruction_context.get_index_of_instruction_account_in_transaction(2)?
|
||||||
== instruction_context.get_index_in_transaction(
|
|
||||||
instruction_context
|
|
||||||
.get_number_of_program_accounts()
|
|
||||||
.saturating_add(2),
|
|
||||||
)?
|
|
||||||
{
|
{
|
||||||
ic_msg!(
|
ic_msg!(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
|
|
|
@ -246,7 +246,7 @@ fn run_program(name: &str) -> u64 {
|
||||||
.get_current_instruction_context()
|
.get_current_instruction_context()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let caller = *instruction_context
|
let caller = *instruction_context
|
||||||
.get_program_key(transaction_context)
|
.get_last_program_key(transaction_context)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
transaction_context
|
transaction_context
|
||||||
.set_return_data(caller, Vec::new())
|
.set_return_data(caller, Vec::new())
|
||||||
|
|
|
@ -92,12 +92,12 @@ fn create_inputs() -> TransactionContext {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(
|
.map(
|
||||||
|(index_in_instruction, index_in_transaction)| InstructionAccount {
|
|(instruction_account_index, index_in_transaction)| InstructionAccount {
|
||||||
index_in_caller: index_in_instruction,
|
index_in_caller: instruction_account_index,
|
||||||
index_in_transaction,
|
index_in_transaction,
|
||||||
index_in_callee: index_in_instruction,
|
index_in_callee: instruction_account_index,
|
||||||
is_signer: false,
|
is_signer: false,
|
||||||
is_writable: index_in_instruction >= 4,
|
is_writable: instruction_account_index >= 4,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
|
@ -54,7 +54,7 @@ use {
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
saturating_add_assign,
|
saturating_add_assign,
|
||||||
system_instruction::{self, MAX_PERMITTED_DATA_LENGTH},
|
system_instruction::{self, MAX_PERMITTED_DATA_LENGTH},
|
||||||
transaction_context::{InstructionContext, TransactionContext},
|
transaction_context::{BorrowedAccount, InstructionContext, TransactionContext},
|
||||||
},
|
},
|
||||||
std::{cell::RefCell, fmt::Debug, rc::Rc, sync::Arc},
|
std::{cell::RefCell, fmt::Debug, rc::Rc, sync::Arc},
|
||||||
thiserror::Error,
|
thiserror::Error,
|
||||||
|
@ -103,6 +103,40 @@ mod executor_metrics {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// The BPF loader is special in that it is the only place in the runtime and its built-in programs,
|
||||||
|
// where data comes not only from instruction account but also program accounts.
|
||||||
|
// Thus, these two helper methods have to distinguish the mixed sources via index_in_instruction.
|
||||||
|
|
||||||
|
fn get_index_in_transaction(
|
||||||
|
instruction_context: &InstructionContext,
|
||||||
|
index_in_instruction: usize,
|
||||||
|
) -> Result<usize, InstructionError> {
|
||||||
|
if index_in_instruction < instruction_context.get_number_of_program_accounts() {
|
||||||
|
instruction_context.get_index_of_program_account_in_transaction(index_in_instruction)
|
||||||
|
} else {
|
||||||
|
instruction_context.get_index_of_instruction_account_in_transaction(
|
||||||
|
index_in_instruction
|
||||||
|
.saturating_sub(instruction_context.get_number_of_program_accounts()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn try_borrow_account<'a>(
|
||||||
|
transaction_context: &'a TransactionContext,
|
||||||
|
instruction_context: &'a InstructionContext,
|
||||||
|
index_in_instruction: usize,
|
||||||
|
) -> Result<BorrowedAccount<'a>, InstructionError> {
|
||||||
|
if index_in_instruction < instruction_context.get_number_of_program_accounts() {
|
||||||
|
instruction_context.try_borrow_program_account(transaction_context, index_in_instruction)
|
||||||
|
} else {
|
||||||
|
instruction_context.try_borrow_instruction_account(
|
||||||
|
transaction_context,
|
||||||
|
index_in_instruction
|
||||||
|
.saturating_sub(instruction_context.get_number_of_program_accounts()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn create_executor(
|
pub fn create_executor(
|
||||||
programdata_account_index: usize,
|
programdata_account_index: usize,
|
||||||
programdata_offset: usize,
|
programdata_offset: usize,
|
||||||
|
@ -160,8 +194,11 @@ pub fn create_executor(
|
||||||
let executable = {
|
let executable = {
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
let programdata = instruction_context
|
let programdata = try_borrow_account(
|
||||||
.try_borrow_account(transaction_context, programdata_account_index)?;
|
transaction_context,
|
||||||
|
instruction_context,
|
||||||
|
programdata_account_index,
|
||||||
|
)?;
|
||||||
create_executor_metrics.program_id = programdata.get_key().to_string();
|
create_executor_metrics.program_id = programdata.get_key().to_string();
|
||||||
let mut load_elf_time = Measure::start("load_elf_time");
|
let mut load_elf_time = Measure::start("load_elf_time");
|
||||||
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
let executable = Executable::<BpfError, ThisInstructionMeter>::from_elf(
|
||||||
|
@ -222,8 +259,11 @@ fn write_program_data(
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
let mut program =
|
let mut program = try_borrow_account(
|
||||||
instruction_context.try_borrow_account(transaction_context, program_account_index)?;
|
transaction_context,
|
||||||
|
instruction_context,
|
||||||
|
program_account_index,
|
||||||
|
)?;
|
||||||
let data = program.get_data_mut()?;
|
let data = program.get_data_mut()?;
|
||||||
let write_offset = program_data_offset.saturating_add(bytes.len());
|
let write_offset = program_data_offset.saturating_add(bytes.len());
|
||||||
if data.len() < write_offset {
|
if data.len() < write_offset {
|
||||||
|
@ -296,15 +336,17 @@ fn process_instruction_common(
|
||||||
let log_collector = invoke_context.get_log_collector();
|
let log_collector = invoke_context.get_log_collector();
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
let program_id = instruction_context.get_program_key(transaction_context)?;
|
let program_id = instruction_context.get_last_program_key(transaction_context)?;
|
||||||
let first_account_key = transaction_context.get_key_of_account_at_index(
|
let first_account_key = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(first_instruction_account)?,
|
get_index_in_transaction(instruction_context, first_instruction_account)?,
|
||||||
)?;
|
)?;
|
||||||
let second_account_key = instruction_context
|
let second_account_key = get_index_in_transaction(
|
||||||
.get_index_in_transaction(first_instruction_account.saturating_add(1))
|
instruction_context,
|
||||||
.and_then(|index_in_transaction| {
|
first_instruction_account.saturating_add(1),
|
||||||
transaction_context.get_key_of_account_at_index(index_in_transaction)
|
)
|
||||||
});
|
.and_then(|index_in_transaction| {
|
||||||
|
transaction_context.get_key_of_account_at_index(index_in_transaction)
|
||||||
|
});
|
||||||
|
|
||||||
let program_account_index = if first_account_key == program_id {
|
let program_account_index = if first_account_key == program_id {
|
||||||
first_instruction_account
|
first_instruction_account
|
||||||
|
@ -314,18 +356,23 @@ fn process_instruction_common(
|
||||||
{
|
{
|
||||||
first_instruction_account.saturating_add(1)
|
first_instruction_account.saturating_add(1)
|
||||||
} else {
|
} else {
|
||||||
if instruction_context
|
let first_account = try_borrow_account(
|
||||||
.try_borrow_account(transaction_context, first_instruction_account)?
|
transaction_context,
|
||||||
.is_executable()
|
instruction_context,
|
||||||
{
|
first_instruction_account,
|
||||||
|
)?;
|
||||||
|
if first_account.is_executable() {
|
||||||
ic_logger_msg!(log_collector, "BPF loader is executable");
|
ic_logger_msg!(log_collector, "BPF loader is executable");
|
||||||
return Err(InstructionError::IncorrectProgramId);
|
return Err(InstructionError::IncorrectProgramId);
|
||||||
}
|
}
|
||||||
first_instruction_account
|
first_instruction_account
|
||||||
};
|
};
|
||||||
|
|
||||||
let program =
|
let program = try_borrow_account(
|
||||||
instruction_context.try_borrow_account(transaction_context, program_account_index)?;
|
transaction_context,
|
||||||
|
instruction_context,
|
||||||
|
program_account_index,
|
||||||
|
)?;
|
||||||
if program.is_executable() {
|
if program.is_executable() {
|
||||||
// First instruction account can only be zero if called from CPI, which
|
// First instruction account can only be zero if called from CPI, which
|
||||||
// means stack height better be greater than one
|
// means stack height better be greater than one
|
||||||
|
@ -356,7 +403,7 @@ fn process_instruction_common(
|
||||||
}
|
}
|
||||||
if !matches!(
|
if !matches!(
|
||||||
instruction_context
|
instruction_context
|
||||||
.try_borrow_account(transaction_context, first_instruction_account)?
|
.try_borrow_program_account(transaction_context, first_instruction_account)?
|
||||||
.get_state()?,
|
.get_state()?,
|
||||||
UpgradeableLoaderState::ProgramData {
|
UpgradeableLoaderState::ProgramData {
|
||||||
slot: _,
|
slot: _,
|
||||||
|
@ -391,7 +438,7 @@ fn process_instruction_common(
|
||||||
)?;
|
)?;
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
let program_id = instruction_context.get_program_key(transaction_context)?;
|
let program_id = instruction_context.get_last_program_key(transaction_context)?;
|
||||||
invoke_context.add_executor(program_id, executor.clone());
|
invoke_context.add_executor(program_id, executor.clone());
|
||||||
executor
|
executor
|
||||||
}
|
}
|
||||||
|
@ -438,7 +485,7 @@ fn process_loader_upgradeable_instruction(
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
let instruction_data = instruction_context.get_instruction_data();
|
let instruction_data = instruction_context.get_instruction_data();
|
||||||
let program_id = instruction_context.get_program_key(transaction_context)?;
|
let program_id = instruction_context.get_last_program_key(transaction_context)?;
|
||||||
|
|
||||||
match limited_deserialize(instruction_data)? {
|
match limited_deserialize(instruction_data)? {
|
||||||
UpgradeableLoaderInstruction::InitializeBuffer => {
|
UpgradeableLoaderInstruction::InitializeBuffer => {
|
||||||
|
@ -451,12 +498,9 @@ fn process_loader_upgradeable_instruction(
|
||||||
return Err(InstructionError::AccountAlreadyInitialized);
|
return Err(InstructionError::AccountAlreadyInitialized);
|
||||||
}
|
}
|
||||||
|
|
||||||
let authority_key = Some(
|
let authority_key = Some(*transaction_context.get_key_of_account_at_index(
|
||||||
*transaction_context.get_key_of_account_at_index(
|
instruction_context.get_index_of_instruction_account_in_transaction(1)?,
|
||||||
instruction_context
|
)?);
|
||||||
.get_index_in_transaction(first_instruction_account.saturating_add(1))?,
|
|
||||||
)?,
|
|
||||||
);
|
|
||||||
|
|
||||||
buffer.set_state(&UpgradeableLoaderState::Buffer {
|
buffer.set_state(&UpgradeableLoaderState::Buffer {
|
||||||
authority_address: authority_key,
|
authority_address: authority_key,
|
||||||
|
@ -472,17 +516,14 @@ fn process_loader_upgradeable_instruction(
|
||||||
ic_logger_msg!(log_collector, "Buffer is immutable");
|
ic_logger_msg!(log_collector, "Buffer is immutable");
|
||||||
return Err(InstructionError::Immutable); // TODO better error code
|
return Err(InstructionError::Immutable); // TODO better error code
|
||||||
}
|
}
|
||||||
let authority_key =
|
let authority_key = Some(*transaction_context.get_key_of_account_at_index(
|
||||||
Some(*transaction_context.get_key_of_account_at_index(
|
instruction_context.get_index_of_instruction_account_in_transaction(1)?,
|
||||||
instruction_context.get_index_in_transaction(
|
)?);
|
||||||
first_instruction_account.saturating_add(1),
|
|
||||||
)?,
|
|
||||||
)?);
|
|
||||||
if authority_address != authority_key {
|
if authority_address != authority_key {
|
||||||
ic_logger_msg!(log_collector, "Incorrect buffer authority provided");
|
ic_logger_msg!(log_collector, "Incorrect buffer authority provided");
|
||||||
return Err(InstructionError::IncorrectAuthority);
|
return Err(InstructionError::IncorrectAuthority);
|
||||||
}
|
}
|
||||||
if !instruction_context.is_signer(first_instruction_account.saturating_add(1))? {
|
if !instruction_context.is_instruction_account_signer(1)? {
|
||||||
ic_logger_msg!(log_collector, "Buffer authority did not sign");
|
ic_logger_msg!(log_collector, "Buffer authority did not sign");
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
|
@ -501,22 +542,18 @@ fn process_loader_upgradeable_instruction(
|
||||||
UpgradeableLoaderInstruction::DeployWithMaxDataLen { max_data_len } => {
|
UpgradeableLoaderInstruction::DeployWithMaxDataLen { max_data_len } => {
|
||||||
instruction_context.check_number_of_instruction_accounts(4)?;
|
instruction_context.check_number_of_instruction_accounts(4)?;
|
||||||
let payer_key = *transaction_context.get_key_of_account_at_index(
|
let payer_key = *transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(first_instruction_account)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(0)?,
|
||||||
)?;
|
)?;
|
||||||
let programdata_key = *transaction_context.get_key_of_account_at_index(
|
let programdata_key = *transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context
|
instruction_context.get_index_of_instruction_account_in_transaction(1)?,
|
||||||
.get_index_in_transaction(first_instruction_account.saturating_add(1))?,
|
|
||||||
)?;
|
)?;
|
||||||
let rent = get_sysvar_with_account_check::rent(invoke_context, instruction_context, 4)?;
|
let rent = get_sysvar_with_account_check::rent(invoke_context, instruction_context, 4)?;
|
||||||
let clock =
|
let clock =
|
||||||
get_sysvar_with_account_check::clock(invoke_context, instruction_context, 5)?;
|
get_sysvar_with_account_check::clock(invoke_context, instruction_context, 5)?;
|
||||||
instruction_context.check_number_of_instruction_accounts(8)?;
|
instruction_context.check_number_of_instruction_accounts(8)?;
|
||||||
let authority_key = Some(
|
let authority_key = Some(*transaction_context.get_key_of_account_at_index(
|
||||||
*transaction_context.get_key_of_account_at_index(
|
instruction_context.get_index_of_instruction_account_in_transaction(7)?,
|
||||||
instruction_context
|
)?);
|
||||||
.get_index_in_transaction(first_instruction_account.saturating_add(7))?,
|
|
||||||
)?,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Verify Program account
|
// Verify Program account
|
||||||
|
|
||||||
|
@ -546,7 +583,7 @@ fn process_loader_upgradeable_instruction(
|
||||||
ic_logger_msg!(log_collector, "Buffer and upgrade authority don't match");
|
ic_logger_msg!(log_collector, "Buffer and upgrade authority don't match");
|
||||||
return Err(InstructionError::IncorrectAuthority);
|
return Err(InstructionError::IncorrectAuthority);
|
||||||
}
|
}
|
||||||
if !instruction_context.is_signer(first_instruction_account.saturating_add(7))? {
|
if !instruction_context.is_instruction_account_signer(7)? {
|
||||||
ic_logger_msg!(log_collector, "Upgrade authority did not sign");
|
ic_logger_msg!(log_collector, "Upgrade authority did not sign");
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
|
@ -617,7 +654,8 @@ fn process_loader_upgradeable_instruction(
|
||||||
|
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
let caller_program_id = instruction_context.get_program_key(transaction_context)?;
|
let caller_program_id =
|
||||||
|
instruction_context.get_last_program_key(transaction_context)?;
|
||||||
let signers = [&[new_program_id.as_ref(), &[bump_seed]]]
|
let signers = [&[new_program_id.as_ref(), &[bump_seed]]]
|
||||||
.iter()
|
.iter()
|
||||||
.map(|seeds| Pubkey::create_program_address(*seeds, caller_program_id))
|
.map(|seeds| Pubkey::create_program_address(*seeds, caller_program_id))
|
||||||
|
@ -689,18 +727,15 @@ fn process_loader_upgradeable_instruction(
|
||||||
UpgradeableLoaderInstruction::Upgrade => {
|
UpgradeableLoaderInstruction::Upgrade => {
|
||||||
instruction_context.check_number_of_instruction_accounts(3)?;
|
instruction_context.check_number_of_instruction_accounts(3)?;
|
||||||
let programdata_key = *transaction_context.get_key_of_account_at_index(
|
let programdata_key = *transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(first_instruction_account)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(0)?,
|
||||||
)?;
|
)?;
|
||||||
let rent = get_sysvar_with_account_check::rent(invoke_context, instruction_context, 4)?;
|
let rent = get_sysvar_with_account_check::rent(invoke_context, instruction_context, 4)?;
|
||||||
let clock =
|
let clock =
|
||||||
get_sysvar_with_account_check::clock(invoke_context, instruction_context, 5)?;
|
get_sysvar_with_account_check::clock(invoke_context, instruction_context, 5)?;
|
||||||
instruction_context.check_number_of_instruction_accounts(7)?;
|
instruction_context.check_number_of_instruction_accounts(7)?;
|
||||||
let authority_key = Some(
|
let authority_key = Some(*transaction_context.get_key_of_account_at_index(
|
||||||
*transaction_context.get_key_of_account_at_index(
|
instruction_context.get_index_of_instruction_account_in_transaction(6)?,
|
||||||
instruction_context
|
)?);
|
||||||
.get_index_in_transaction(first_instruction_account.saturating_add(6))?,
|
|
||||||
)?,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Verify Program account
|
// Verify Program account
|
||||||
|
|
||||||
|
@ -742,7 +777,7 @@ fn process_loader_upgradeable_instruction(
|
||||||
ic_logger_msg!(log_collector, "Buffer and upgrade authority don't match");
|
ic_logger_msg!(log_collector, "Buffer and upgrade authority don't match");
|
||||||
return Err(InstructionError::IncorrectAuthority);
|
return Err(InstructionError::IncorrectAuthority);
|
||||||
}
|
}
|
||||||
if !instruction_context.is_signer(first_instruction_account.saturating_add(6))? {
|
if !instruction_context.is_instruction_account_signer(6)? {
|
||||||
ic_logger_msg!(log_collector, "Upgrade authority did not sign");
|
ic_logger_msg!(log_collector, "Upgrade authority did not sign");
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
|
@ -796,7 +831,7 @@ fn process_loader_upgradeable_instruction(
|
||||||
ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
|
ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
|
||||||
return Err(InstructionError::IncorrectAuthority);
|
return Err(InstructionError::IncorrectAuthority);
|
||||||
}
|
}
|
||||||
if !instruction_context.is_signer(first_instruction_account.saturating_add(6))? {
|
if !instruction_context.is_instruction_account_signer(6)? {
|
||||||
ic_logger_msg!(log_collector, "Upgrade authority did not sign");
|
ic_logger_msg!(log_collector, "Upgrade authority did not sign");
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
|
@ -878,11 +913,10 @@ fn process_loader_upgradeable_instruction(
|
||||||
let mut account =
|
let mut account =
|
||||||
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||||
let present_authority_key = transaction_context.get_key_of_account_at_index(
|
let present_authority_key = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context
|
instruction_context.get_index_of_instruction_account_in_transaction(1)?,
|
||||||
.get_index_in_transaction(first_instruction_account.saturating_add(1))?,
|
|
||||||
)?;
|
)?;
|
||||||
let new_authority = instruction_context
|
let new_authority = instruction_context
|
||||||
.get_index_in_transaction(first_instruction_account.saturating_add(2))
|
.get_index_of_instruction_account_in_transaction(2)
|
||||||
.and_then(|index_in_transaction| {
|
.and_then(|index_in_transaction| {
|
||||||
transaction_context.get_key_of_account_at_index(index_in_transaction)
|
transaction_context.get_key_of_account_at_index(index_in_transaction)
|
||||||
})
|
})
|
||||||
|
@ -902,9 +936,7 @@ fn process_loader_upgradeable_instruction(
|
||||||
ic_logger_msg!(log_collector, "Incorrect buffer authority provided");
|
ic_logger_msg!(log_collector, "Incorrect buffer authority provided");
|
||||||
return Err(InstructionError::IncorrectAuthority);
|
return Err(InstructionError::IncorrectAuthority);
|
||||||
}
|
}
|
||||||
if !instruction_context
|
if !instruction_context.is_instruction_account_signer(1)? {
|
||||||
.is_signer(first_instruction_account.saturating_add(1))?
|
|
||||||
{
|
|
||||||
ic_logger_msg!(log_collector, "Buffer authority did not sign");
|
ic_logger_msg!(log_collector, "Buffer authority did not sign");
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
|
@ -924,9 +956,7 @@ fn process_loader_upgradeable_instruction(
|
||||||
ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
|
ic_logger_msg!(log_collector, "Incorrect upgrade authority provided");
|
||||||
return Err(InstructionError::IncorrectAuthority);
|
return Err(InstructionError::IncorrectAuthority);
|
||||||
}
|
}
|
||||||
if !instruction_context
|
if !instruction_context.is_instruction_account_signer(1)? {
|
||||||
.is_signer(first_instruction_account.saturating_add(1))?
|
|
||||||
{
|
|
||||||
ic_logger_msg!(log_collector, "Upgrade authority did not sign");
|
ic_logger_msg!(log_collector, "Upgrade authority did not sign");
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
|
@ -945,9 +975,8 @@ fn process_loader_upgradeable_instruction(
|
||||||
}
|
}
|
||||||
UpgradeableLoaderInstruction::Close => {
|
UpgradeableLoaderInstruction::Close => {
|
||||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||||
if instruction_context.get_index_in_transaction(first_instruction_account)?
|
if instruction_context.get_index_of_instruction_account_in_transaction(0)?
|
||||||
== instruction_context
|
== instruction_context.get_index_of_instruction_account_in_transaction(1)?
|
||||||
.get_index_in_transaction(first_instruction_account.saturating_add(1))?
|
|
||||||
{
|
{
|
||||||
ic_logger_msg!(
|
ic_logger_msg!(
|
||||||
log_collector,
|
log_collector,
|
||||||
|
@ -1050,16 +1079,14 @@ fn common_close_account(
|
||||||
return Err(InstructionError::Immutable);
|
return Err(InstructionError::Immutable);
|
||||||
}
|
}
|
||||||
if *authority_address
|
if *authority_address
|
||||||
!= Some(*instruction_context.get_instruction_account_key(transaction_context, 2)?)
|
!= Some(*transaction_context.get_key_of_account_at_index(
|
||||||
|
instruction_context.get_index_of_instruction_account_in_transaction(2)?,
|
||||||
|
)?)
|
||||||
{
|
{
|
||||||
ic_logger_msg!(log_collector, "Incorrect authority provided");
|
ic_logger_msg!(log_collector, "Incorrect authority provided");
|
||||||
return Err(InstructionError::IncorrectAuthority);
|
return Err(InstructionError::IncorrectAuthority);
|
||||||
}
|
}
|
||||||
if !instruction_context.is_signer(
|
if !instruction_context.is_instruction_account_signer(2)? {
|
||||||
instruction_context
|
|
||||||
.get_number_of_program_accounts()
|
|
||||||
.saturating_add(2),
|
|
||||||
)? {
|
|
||||||
ic_logger_msg!(log_collector, "Authority did not sign");
|
ic_logger_msg!(log_collector, "Authority did not sign");
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
|
@ -1082,7 +1109,7 @@ fn process_loader_instruction(
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
let instruction_data = instruction_context.get_instruction_data();
|
let instruction_data = instruction_context.get_instruction_data();
|
||||||
let program_id = instruction_context.get_program_key(transaction_context)?;
|
let program_id = instruction_context.get_last_program_key(transaction_context)?;
|
||||||
let program = instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
let program = instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||||
if program.get_owner() != program_id {
|
if program.get_owner() != program_id {
|
||||||
ic_msg!(
|
ic_msg!(
|
||||||
|
@ -1178,7 +1205,7 @@ impl Executor for BpfExecutor {
|
||||||
let stack_height = invoke_context.get_stack_height();
|
let stack_height = invoke_context.get_stack_height();
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
let program_id = *instruction_context.get_program_key(transaction_context)?;
|
let program_id = *instruction_context.get_last_program_key(transaction_context)?;
|
||||||
|
|
||||||
let mut serialize_time = Measure::start("serialize");
|
let mut serialize_time = Measure::start("serialize");
|
||||||
let (mut parameter_bytes, account_lengths) =
|
let (mut parameter_bytes, account_lengths) =
|
||||||
|
|
|
@ -19,7 +19,7 @@ pub fn serialize_parameters(
|
||||||
instruction_context: &InstructionContext,
|
instruction_context: &InstructionContext,
|
||||||
) -> Result<(AlignedMemory, Vec<usize>), InstructionError> {
|
) -> Result<(AlignedMemory, Vec<usize>), InstructionError> {
|
||||||
let is_loader_deprecated = *instruction_context
|
let is_loader_deprecated = *instruction_context
|
||||||
.try_borrow_program_account(transaction_context)?
|
.try_borrow_last_program_account(transaction_context)?
|
||||||
.get_owner()
|
.get_owner()
|
||||||
== bpf_loader_deprecated::id();
|
== bpf_loader_deprecated::id();
|
||||||
if is_loader_deprecated {
|
if is_loader_deprecated {
|
||||||
|
@ -28,11 +28,10 @@ pub fn serialize_parameters(
|
||||||
serialize_parameters_aligned(transaction_context, instruction_context)
|
serialize_parameters_aligned(transaction_context, instruction_context)
|
||||||
}
|
}
|
||||||
.and_then(|buffer| {
|
.and_then(|buffer| {
|
||||||
let account_lengths = (instruction_context.get_number_of_program_accounts()
|
let account_lengths = (0..instruction_context.get_number_of_instruction_accounts())
|
||||||
..instruction_context.get_number_of_accounts())
|
.map(|instruction_account_index| {
|
||||||
.map(|index_in_instruction| {
|
|
||||||
Ok(instruction_context
|
Ok(instruction_context
|
||||||
.try_borrow_account(transaction_context, index_in_instruction)?
|
.try_borrow_instruction_account(transaction_context, instruction_account_index)?
|
||||||
.get_data()
|
.get_data()
|
||||||
.len())
|
.len())
|
||||||
})
|
})
|
||||||
|
@ -48,7 +47,7 @@ pub fn deserialize_parameters(
|
||||||
account_lengths: &[usize],
|
account_lengths: &[usize],
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let is_loader_deprecated = *instruction_context
|
let is_loader_deprecated = *instruction_context
|
||||||
.try_borrow_program_account(transaction_context)?
|
.try_borrow_last_program_account(transaction_context)?
|
||||||
.get_owner()
|
.get_owner()
|
||||||
== bpf_loader_deprecated::id();
|
== bpf_loader_deprecated::id();
|
||||||
if is_loader_deprecated {
|
if is_loader_deprecated {
|
||||||
|
@ -74,14 +73,13 @@ pub fn serialize_parameters_unaligned(
|
||||||
) -> Result<AlignedMemory, InstructionError> {
|
) -> Result<AlignedMemory, InstructionError> {
|
||||||
// Calculate size in order to alloc once
|
// Calculate size in order to alloc once
|
||||||
let mut size = size_of::<u64>();
|
let mut size = size_of::<u64>();
|
||||||
for index_in_instruction in instruction_context.get_number_of_program_accounts()
|
for instruction_account_index in 0..instruction_context.get_number_of_instruction_accounts() {
|
||||||
..instruction_context.get_number_of_accounts()
|
let duplicate =
|
||||||
{
|
instruction_context.is_instruction_account_duplicate(instruction_account_index)?;
|
||||||
let duplicate = instruction_context.is_duplicate(index_in_instruction)?;
|
|
||||||
size += 1; // dup
|
size += 1; // dup
|
||||||
if duplicate.is_none() {
|
if duplicate.is_none() {
|
||||||
let data_len = instruction_context
|
let data_len = instruction_context
|
||||||
.try_borrow_account(transaction_context, index_in_instruction)?
|
.try_borrow_instruction_account(transaction_context, instruction_account_index)?
|
||||||
.get_data()
|
.get_data()
|
||||||
.len();
|
.len();
|
||||||
size += size_of::<u8>() // is_signer
|
size += size_of::<u8>() // is_signer
|
||||||
|
@ -102,16 +100,15 @@ pub fn serialize_parameters_unaligned(
|
||||||
|
|
||||||
v.write_u64::<LittleEndian>(instruction_context.get_number_of_instruction_accounts() as u64)
|
v.write_u64::<LittleEndian>(instruction_context.get_number_of_instruction_accounts() as u64)
|
||||||
.map_err(|_| InstructionError::InvalidArgument)?;
|
.map_err(|_| InstructionError::InvalidArgument)?;
|
||||||
for index_in_instruction in instruction_context.get_number_of_program_accounts()
|
for instruction_account_index in 0..instruction_context.get_number_of_instruction_accounts() {
|
||||||
..instruction_context.get_number_of_accounts()
|
let duplicate =
|
||||||
{
|
instruction_context.is_instruction_account_duplicate(instruction_account_index)?;
|
||||||
let duplicate = instruction_context.is_duplicate(index_in_instruction)?;
|
|
||||||
if let Some(position) = duplicate {
|
if let Some(position) = duplicate {
|
||||||
v.write_u8(position as u8)
|
v.write_u8(position as u8)
|
||||||
.map_err(|_| InstructionError::InvalidArgument)?;
|
.map_err(|_| InstructionError::InvalidArgument)?;
|
||||||
} else {
|
} else {
|
||||||
let borrowed_account = instruction_context
|
let borrowed_account = instruction_context
|
||||||
.try_borrow_account(transaction_context, index_in_instruction)?;
|
.try_borrow_instruction_account(transaction_context, instruction_account_index)?;
|
||||||
v.write_u8(std::u8::MAX)
|
v.write_u8(std::u8::MAX)
|
||||||
.map_err(|_| InstructionError::InvalidArgument)?;
|
.map_err(|_| InstructionError::InvalidArgument)?;
|
||||||
v.write_u8(borrowed_account.is_signer() as u8)
|
v.write_u8(borrowed_account.is_signer() as u8)
|
||||||
|
@ -140,7 +137,7 @@ pub fn serialize_parameters_unaligned(
|
||||||
.map_err(|_| InstructionError::InvalidArgument)?;
|
.map_err(|_| InstructionError::InvalidArgument)?;
|
||||||
v.write_all(
|
v.write_all(
|
||||||
instruction_context
|
instruction_context
|
||||||
.try_borrow_program_account(transaction_context)?
|
.try_borrow_last_program_account(transaction_context)?
|
||||||
.get_key()
|
.get_key()
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
)
|
)
|
||||||
|
@ -155,15 +152,15 @@ pub fn deserialize_parameters_unaligned(
|
||||||
account_lengths: &[usize],
|
account_lengths: &[usize],
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let mut start = size_of::<u64>(); // number of accounts
|
let mut start = size_of::<u64>(); // number of accounts
|
||||||
for (index_in_instruction, pre_len) in (instruction_context.get_number_of_program_accounts()
|
for (instruction_account_index, pre_len) in
|
||||||
..instruction_context.get_number_of_accounts())
|
(0..instruction_context.get_number_of_instruction_accounts()).zip(account_lengths.iter())
|
||||||
.zip(account_lengths.iter())
|
|
||||||
{
|
{
|
||||||
let duplicate = instruction_context.is_duplicate(index_in_instruction)?;
|
let duplicate =
|
||||||
|
instruction_context.is_instruction_account_duplicate(instruction_account_index)?;
|
||||||
start += 1; // is_dup
|
start += 1; // is_dup
|
||||||
if duplicate.is_none() {
|
if duplicate.is_none() {
|
||||||
let mut borrowed_account = instruction_context
|
let mut borrowed_account = instruction_context
|
||||||
.try_borrow_account(transaction_context, index_in_instruction)?;
|
.try_borrow_instruction_account(transaction_context, instruction_account_index)?;
|
||||||
start += size_of::<u8>(); // is_signer
|
start += size_of::<u8>(); // is_signer
|
||||||
start += size_of::<u8>(); // is_writable
|
start += size_of::<u8>(); // is_writable
|
||||||
start += size_of::<Pubkey>(); // key
|
start += size_of::<Pubkey>(); // key
|
||||||
|
@ -194,16 +191,15 @@ pub fn serialize_parameters_aligned(
|
||||||
) -> Result<AlignedMemory, InstructionError> {
|
) -> Result<AlignedMemory, InstructionError> {
|
||||||
// Calculate size in order to alloc once
|
// Calculate size in order to alloc once
|
||||||
let mut size = size_of::<u64>();
|
let mut size = size_of::<u64>();
|
||||||
for index_in_instruction in instruction_context.get_number_of_program_accounts()
|
for instruction_account_index in 0..instruction_context.get_number_of_instruction_accounts() {
|
||||||
..instruction_context.get_number_of_accounts()
|
let duplicate =
|
||||||
{
|
instruction_context.is_instruction_account_duplicate(instruction_account_index)?;
|
||||||
let duplicate = instruction_context.is_duplicate(index_in_instruction)?;
|
|
||||||
size += 1; // dup
|
size += 1; // dup
|
||||||
if duplicate.is_some() {
|
if duplicate.is_some() {
|
||||||
size += 7; // padding to 64-bit aligned
|
size += 7; // padding to 64-bit aligned
|
||||||
} else {
|
} else {
|
||||||
let data_len = instruction_context
|
let data_len = instruction_context
|
||||||
.try_borrow_account(transaction_context, index_in_instruction)?
|
.try_borrow_instruction_account(transaction_context, instruction_account_index)?
|
||||||
.get_data()
|
.get_data()
|
||||||
.len();
|
.len();
|
||||||
size += size_of::<u8>() // is_signer
|
size += size_of::<u8>() // is_signer
|
||||||
|
@ -228,10 +224,9 @@ pub fn serialize_parameters_aligned(
|
||||||
// Serialize into the buffer
|
// Serialize into the buffer
|
||||||
v.write_u64::<LittleEndian>(instruction_context.get_number_of_instruction_accounts() as u64)
|
v.write_u64::<LittleEndian>(instruction_context.get_number_of_instruction_accounts() as u64)
|
||||||
.map_err(|_| InstructionError::InvalidArgument)?;
|
.map_err(|_| InstructionError::InvalidArgument)?;
|
||||||
for index_in_instruction in instruction_context.get_number_of_program_accounts()
|
for instruction_account_index in 0..instruction_context.get_number_of_instruction_accounts() {
|
||||||
..instruction_context.get_number_of_accounts()
|
let duplicate =
|
||||||
{
|
instruction_context.is_instruction_account_duplicate(instruction_account_index)?;
|
||||||
let duplicate = instruction_context.is_duplicate(index_in_instruction)?;
|
|
||||||
if let Some(position) = duplicate {
|
if let Some(position) = duplicate {
|
||||||
v.write_u8(position as u8)
|
v.write_u8(position as u8)
|
||||||
.map_err(|_| InstructionError::InvalidArgument)?;
|
.map_err(|_| InstructionError::InvalidArgument)?;
|
||||||
|
@ -239,7 +234,7 @@ pub fn serialize_parameters_aligned(
|
||||||
.map_err(|_| InstructionError::InvalidArgument)?; // 7 bytes of padding to make 64-bit aligned
|
.map_err(|_| InstructionError::InvalidArgument)?; // 7 bytes of padding to make 64-bit aligned
|
||||||
} else {
|
} else {
|
||||||
let borrowed_account = instruction_context
|
let borrowed_account = instruction_context
|
||||||
.try_borrow_account(transaction_context, index_in_instruction)?;
|
.try_borrow_instruction_account(transaction_context, instruction_account_index)?;
|
||||||
v.write_u8(std::u8::MAX)
|
v.write_u8(std::u8::MAX)
|
||||||
.map_err(|_| InstructionError::InvalidArgument)?;
|
.map_err(|_| InstructionError::InvalidArgument)?;
|
||||||
v.write_u8(borrowed_account.is_signer() as u8)
|
v.write_u8(borrowed_account.is_signer() as u8)
|
||||||
|
@ -276,7 +271,7 @@ pub fn serialize_parameters_aligned(
|
||||||
.map_err(|_| InstructionError::InvalidArgument)?;
|
.map_err(|_| InstructionError::InvalidArgument)?;
|
||||||
v.write_all(
|
v.write_all(
|
||||||
instruction_context
|
instruction_context
|
||||||
.try_borrow_program_account(transaction_context)?
|
.try_borrow_last_program_account(transaction_context)?
|
||||||
.get_key()
|
.get_key()
|
||||||
.as_ref(),
|
.as_ref(),
|
||||||
)
|
)
|
||||||
|
@ -291,17 +286,17 @@ pub fn deserialize_parameters_aligned(
|
||||||
account_lengths: &[usize],
|
account_lengths: &[usize],
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let mut start = size_of::<u64>(); // number of accounts
|
let mut start = size_of::<u64>(); // number of accounts
|
||||||
for (index_in_instruction, pre_len) in (instruction_context.get_number_of_program_accounts()
|
for (instruction_account_index, pre_len) in
|
||||||
..instruction_context.get_number_of_accounts())
|
(0..instruction_context.get_number_of_instruction_accounts()).zip(account_lengths.iter())
|
||||||
.zip(account_lengths.iter())
|
|
||||||
{
|
{
|
||||||
let duplicate = instruction_context.is_duplicate(index_in_instruction)?;
|
let duplicate =
|
||||||
|
instruction_context.is_instruction_account_duplicate(instruction_account_index)?;
|
||||||
start += size_of::<u8>(); // position
|
start += size_of::<u8>(); // position
|
||||||
if duplicate.is_some() {
|
if duplicate.is_some() {
|
||||||
start += 7; // padding to 64-bit aligned
|
start += 7; // padding to 64-bit aligned
|
||||||
} else {
|
} else {
|
||||||
let mut borrowed_account = instruction_context
|
let mut borrowed_account = instruction_context
|
||||||
.try_borrow_account(transaction_context, index_in_instruction)?;
|
.try_borrow_instruction_account(transaction_context, instruction_account_index)?;
|
||||||
start += size_of::<u8>() // is_signer
|
start += size_of::<u8>() // is_signer
|
||||||
+ size_of::<u8>() // is_writable
|
+ size_of::<u8>() // is_writable
|
||||||
+ size_of::<u8>() // executable
|
+ size_of::<u8>() // executable
|
||||||
|
@ -442,11 +437,13 @@ mod tests {
|
||||||
let instruction_accounts = [1, 1, 2, 3, 4, 4, 5, 6]
|
let instruction_accounts = [1, 1, 2, 3, 4, 4, 5, 6]
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.map(|(index_in_instruction, index_in_transaction)| AccountMeta {
|
.map(
|
||||||
pubkey: transaction_accounts.get(index_in_transaction).unwrap().0,
|
|(instruction_account_index, index_in_transaction)| AccountMeta {
|
||||||
is_signer: false,
|
pubkey: transaction_accounts.get(index_in_transaction).unwrap().0,
|
||||||
is_writable: index_in_instruction >= 4,
|
is_signer: false,
|
||||||
})
|
is_writable: instruction_account_index >= 4,
|
||||||
|
},
|
||||||
|
)
|
||||||
.collect();
|
.collect();
|
||||||
let instruction_data = vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
let instruction_data = vec![1u8, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11];
|
||||||
let program_indices = [0];
|
let program_indices = [0];
|
||||||
|
@ -552,7 +549,7 @@ mod tests {
|
||||||
.transaction_context
|
.transaction_context
|
||||||
.get_current_instruction_context()
|
.get_current_instruction_context()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.try_borrow_account(invoke_context.transaction_context, 0)
|
.try_borrow_program_account(invoke_context.transaction_context, 0)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.set_owner(bpf_loader_deprecated::id().as_ref());
|
.set_owner(bpf_loader_deprecated::id().as_ref());
|
||||||
|
|
||||||
|
|
|
@ -369,7 +369,8 @@ pub fn bind_syscall_context_objects<'a, 'b>(
|
||||||
.transaction_context
|
.transaction_context
|
||||||
.get_current_instruction_context()
|
.get_current_instruction_context()
|
||||||
.and_then(|instruction_context| {
|
.and_then(|instruction_context| {
|
||||||
instruction_context.try_borrow_program_account(invoke_context.transaction_context)
|
instruction_context
|
||||||
|
.try_borrow_last_program_account(invoke_context.transaction_context)
|
||||||
})
|
})
|
||||||
.map(|program_account| *program_account.get_owner())
|
.map(|program_account| *program_account.get_owner())
|
||||||
.map_err(SyscallError::InstructionError)?;
|
.map_err(SyscallError::InstructionError)?;
|
||||||
|
@ -2946,8 +2947,9 @@ where
|
||||||
))?;
|
))?;
|
||||||
accounts.push((*program_account_index, None));
|
accounts.push((*program_account_index, None));
|
||||||
|
|
||||||
for (index_in_instruction, instruction_account) in instruction_accounts.iter().enumerate() {
|
for (instruction_account_index, instruction_account) in instruction_accounts.iter().enumerate()
|
||||||
if index_in_instruction != instruction_account.index_in_callee {
|
{
|
||||||
|
if instruction_account_index != instruction_account.index_in_callee {
|
||||||
continue; // Skip duplicate account
|
continue; // Skip duplicate account
|
||||||
}
|
}
|
||||||
let mut callee_account = instruction_context
|
let mut callee_account = instruction_context
|
||||||
|
@ -3121,7 +3123,7 @@ fn call<'a, 'b: 'a>(
|
||||||
.get_current_instruction_context()
|
.get_current_instruction_context()
|
||||||
.map_err(SyscallError::InstructionError)?;
|
.map_err(SyscallError::InstructionError)?;
|
||||||
let caller_program_id = instruction_context
|
let caller_program_id = instruction_context
|
||||||
.get_program_key(transaction_context)
|
.get_last_program_key(transaction_context)
|
||||||
.map_err(SyscallError::InstructionError)?;
|
.map_err(SyscallError::InstructionError)?;
|
||||||
let signers = syscall.translate_signers(
|
let signers = syscall.translate_signers(
|
||||||
caller_program_id,
|
caller_program_id,
|
||||||
|
@ -3288,9 +3290,8 @@ declare_syscall!(
|
||||||
let program_id = *question_mark!(
|
let program_id = *question_mark!(
|
||||||
transaction_context
|
transaction_context
|
||||||
.get_current_instruction_context()
|
.get_current_instruction_context()
|
||||||
.and_then(
|
.and_then(|instruction_context| instruction_context
|
||||||
|instruction_context| instruction_context.get_program_key(transaction_context)
|
.get_last_program_key(transaction_context))
|
||||||
)
|
|
||||||
.map_err(SyscallError::InstructionError),
|
.map_err(SyscallError::InstructionError),
|
||||||
result
|
result
|
||||||
);
|
);
|
||||||
|
@ -3570,19 +3571,26 @@ declare_syscall!(
|
||||||
result
|
result
|
||||||
);
|
);
|
||||||
|
|
||||||
*program_id =
|
*program_id = *question_mark!(
|
||||||
instruction_context.get_program_id(invoke_context.transaction_context);
|
instruction_context
|
||||||
|
.get_last_program_key(invoke_context.transaction_context)
|
||||||
|
.map_err(SyscallError::InstructionError),
|
||||||
|
result
|
||||||
|
);
|
||||||
data.clone_from_slice(instruction_context.get_instruction_data());
|
data.clone_from_slice(instruction_context.get_instruction_data());
|
||||||
let account_metas = question_mark!(
|
let account_metas = question_mark!(
|
||||||
(instruction_context.get_number_of_program_accounts()
|
(0..instruction_context.get_number_of_instruction_accounts())
|
||||||
..instruction_context.get_number_of_accounts())
|
.map(|instruction_account_index| Ok(AccountMeta {
|
||||||
.map(|index_in_instruction| Ok(AccountMeta {
|
|
||||||
pubkey: *invoke_context.get_key_of_account_at_index(
|
pubkey: *invoke_context.get_key_of_account_at_index(
|
||||||
instruction_context
|
instruction_context
|
||||||
.get_index_in_transaction(index_in_instruction)?
|
.get_index_of_instruction_account_in_transaction(
|
||||||
|
instruction_account_index
|
||||||
|
)?
|
||||||
)?,
|
)?,
|
||||||
is_signer: instruction_context.is_signer(index_in_instruction)?,
|
is_signer: instruction_context
|
||||||
is_writable: instruction_context.is_writable(index_in_instruction)?,
|
.is_instruction_account_signer(instruction_account_index)?,
|
||||||
|
is_writable: instruction_context
|
||||||
|
.is_instruction_account_writable(instruction_account_index)?,
|
||||||
}))
|
}))
|
||||||
.collect::<Result<Vec<_>, InstructionError>>()
|
.collect::<Result<Vec<_>, InstructionError>>()
|
||||||
.map_err(SyscallError::InstructionError),
|
.map_err(SyscallError::InstructionError),
|
||||||
|
|
|
@ -20,11 +20,9 @@ pub fn process_instruction(
|
||||||
let data = instruction_context.get_instruction_data();
|
let data = instruction_context.get_instruction_data();
|
||||||
|
|
||||||
let key_list: ConfigKeys = limited_deserialize(data)?;
|
let key_list: ConfigKeys = limited_deserialize(data)?;
|
||||||
let config_account_key =
|
let config_account_key = transaction_context.get_key_of_account_at_index(
|
||||||
transaction_context
|
instruction_context.get_index_of_instruction_account_in_transaction(0)?,
|
||||||
.get_key_of_account_at_index(instruction_context.get_index_in_transaction(
|
)?;
|
||||||
instruction_context.get_number_of_program_accounts(),
|
|
||||||
)?)?;
|
|
||||||
let config_account =
|
let config_account =
|
||||||
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||||
let is_config_account_signer = config_account.is_signer();
|
let is_config_account_signer = config_account.is_signer();
|
||||||
|
|
|
@ -28,17 +28,23 @@ use {
|
||||||
fn get_optional_pubkey<'a>(
|
fn get_optional_pubkey<'a>(
|
||||||
transaction_context: &'a TransactionContext,
|
transaction_context: &'a TransactionContext,
|
||||||
instruction_context: &'a InstructionContext,
|
instruction_context: &'a InstructionContext,
|
||||||
index_in_instruction: usize,
|
instruction_account_index: usize,
|
||||||
should_be_signer: bool,
|
should_be_signer: bool,
|
||||||
) -> Result<Option<&'a Pubkey>, InstructionError> {
|
) -> Result<Option<&'a Pubkey>, InstructionError> {
|
||||||
Ok(
|
Ok(
|
||||||
if instruction_context.get_number_of_accounts() > index_in_instruction {
|
if instruction_account_index < instruction_context.get_number_of_instruction_accounts() {
|
||||||
if should_be_signer && !instruction_context.is_signer(index_in_instruction)? {
|
if should_be_signer
|
||||||
|
&& !instruction_context.is_instruction_account_signer(instruction_account_index)?
|
||||||
|
{
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
Some(transaction_context.get_key_of_account_at_index(
|
Some(
|
||||||
instruction_context.get_index_in_transaction(index_in_instruction)?,
|
transaction_context.get_key_of_account_at_index(
|
||||||
)?)
|
instruction_context.get_index_of_instruction_account_in_transaction(
|
||||||
|
instruction_account_index,
|
||||||
|
)?,
|
||||||
|
)?,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
|
@ -46,7 +52,7 @@ fn get_optional_pubkey<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_instruction(
|
pub fn process_instruction(
|
||||||
first_instruction_account: usize,
|
_first_instruction_account: usize,
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
|
@ -86,12 +92,8 @@ pub fn process_instruction(
|
||||||
let clock =
|
let clock =
|
||||||
get_sysvar_with_account_check::clock(invoke_context, instruction_context, 1)?;
|
get_sysvar_with_account_check::clock(invoke_context, instruction_context, 1)?;
|
||||||
instruction_context.check_number_of_instruction_accounts(3)?;
|
instruction_context.check_number_of_instruction_accounts(3)?;
|
||||||
let custodian_pubkey = get_optional_pubkey(
|
let custodian_pubkey =
|
||||||
transaction_context,
|
get_optional_pubkey(transaction_context, instruction_context, 3, false)?;
|
||||||
instruction_context,
|
|
||||||
first_instruction_account + 3,
|
|
||||||
false,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
authorize(
|
authorize(
|
||||||
&mut me,
|
&mut me,
|
||||||
|
@ -123,18 +125,14 @@ pub fn process_instruction(
|
||||||
if require_custodian_for_locked_stake_authorize {
|
if require_custodian_for_locked_stake_authorize {
|
||||||
let clock =
|
let clock =
|
||||||
get_sysvar_with_account_check::clock(invoke_context, instruction_context, 2)?;
|
get_sysvar_with_account_check::clock(invoke_context, instruction_context, 2)?;
|
||||||
let custodian_pubkey = get_optional_pubkey(
|
let custodian_pubkey =
|
||||||
transaction_context,
|
get_optional_pubkey(transaction_context, instruction_context, 3, false)?;
|
||||||
instruction_context,
|
|
||||||
first_instruction_account + 3,
|
|
||||||
false,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
authorize_with_seed(
|
authorize_with_seed(
|
||||||
transaction_context,
|
transaction_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
&mut me,
|
&mut me,
|
||||||
first_instruction_account + 1,
|
1,
|
||||||
&args.authority_seed,
|
&args.authority_seed,
|
||||||
&args.authority_owner,
|
&args.authority_owner,
|
||||||
&args.new_authorized_pubkey,
|
&args.new_authorized_pubkey,
|
||||||
|
@ -148,7 +146,7 @@ pub fn process_instruction(
|
||||||
transaction_context,
|
transaction_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
&mut me,
|
&mut me,
|
||||||
first_instruction_account + 1,
|
1,
|
||||||
&args.authority_seed,
|
&args.authority_seed,
|
||||||
&args.authority_owner,
|
&args.authority_owner,
|
||||||
&args.new_authorized_pubkey,
|
&args.new_authorized_pubkey,
|
||||||
|
@ -181,8 +179,8 @@ pub fn process_instruction(
|
||||||
delegate(
|
delegate(
|
||||||
transaction_context,
|
transaction_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
first_instruction_account,
|
0,
|
||||||
first_instruction_account + 1,
|
1,
|
||||||
&clock,
|
&clock,
|
||||||
&stake_history,
|
&stake_history,
|
||||||
&config,
|
&config,
|
||||||
|
@ -198,9 +196,9 @@ pub fn process_instruction(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
transaction_context,
|
transaction_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
first_instruction_account,
|
0,
|
||||||
lamports,
|
lamports,
|
||||||
first_instruction_account + 1,
|
1,
|
||||||
&signers,
|
&signers,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -219,8 +217,8 @@ pub fn process_instruction(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
transaction_context,
|
transaction_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
first_instruction_account,
|
0,
|
||||||
first_instruction_account + 1,
|
1,
|
||||||
&clock,
|
&clock,
|
||||||
&stake_history,
|
&stake_history,
|
||||||
&signers,
|
&signers,
|
||||||
|
@ -241,14 +239,14 @@ pub fn process_instruction(
|
||||||
withdraw(
|
withdraw(
|
||||||
transaction_context,
|
transaction_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
first_instruction_account,
|
0,
|
||||||
lamports,
|
lamports,
|
||||||
first_instruction_account + 1,
|
1,
|
||||||
&clock,
|
&clock,
|
||||||
&stake_history,
|
&stake_history,
|
||||||
first_instruction_account + 4,
|
4,
|
||||||
if instruction_context.get_number_of_instruction_accounts() >= 6 {
|
if instruction_context.get_number_of_instruction_accounts() >= 6 {
|
||||||
Some(first_instruction_account + 5)
|
Some(5)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
},
|
},
|
||||||
|
@ -274,12 +272,12 @@ pub fn process_instruction(
|
||||||
{
|
{
|
||||||
instruction_context.check_number_of_instruction_accounts(4)?;
|
instruction_context.check_number_of_instruction_accounts(4)?;
|
||||||
let staker_pubkey = transaction_context.get_key_of_account_at_index(
|
let staker_pubkey = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(first_instruction_account + 2)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(2)?,
|
||||||
)?;
|
)?;
|
||||||
let withdrawer_pubkey = transaction_context.get_key_of_account_at_index(
|
let withdrawer_pubkey = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(first_instruction_account + 3)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(3)?,
|
||||||
)?;
|
)?;
|
||||||
if !instruction_context.is_signer(first_instruction_account + 3)? {
|
if !instruction_context.is_instruction_account_signer(3)? {
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -311,17 +309,13 @@ pub fn process_instruction(
|
||||||
get_sysvar_with_account_check::clock(invoke_context, instruction_context, 1)?;
|
get_sysvar_with_account_check::clock(invoke_context, instruction_context, 1)?;
|
||||||
instruction_context.check_number_of_instruction_accounts(4)?;
|
instruction_context.check_number_of_instruction_accounts(4)?;
|
||||||
let authorized_pubkey = transaction_context.get_key_of_account_at_index(
|
let authorized_pubkey = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(first_instruction_account + 3)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(3)?,
|
||||||
)?;
|
)?;
|
||||||
if !instruction_context.is_signer(first_instruction_account + 3)? {
|
if !instruction_context.is_instruction_account_signer(3)? {
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
let custodian_pubkey = get_optional_pubkey(
|
let custodian_pubkey =
|
||||||
transaction_context,
|
get_optional_pubkey(transaction_context, instruction_context, 4, false)?;
|
||||||
instruction_context,
|
|
||||||
first_instruction_account + 4,
|
|
||||||
false,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
authorize(
|
authorize(
|
||||||
&mut me,
|
&mut me,
|
||||||
|
@ -347,23 +341,19 @@ pub fn process_instruction(
|
||||||
get_sysvar_with_account_check::clock(invoke_context, instruction_context, 2)?;
|
get_sysvar_with_account_check::clock(invoke_context, instruction_context, 2)?;
|
||||||
instruction_context.check_number_of_instruction_accounts(4)?;
|
instruction_context.check_number_of_instruction_accounts(4)?;
|
||||||
let authorized_pubkey = transaction_context.get_key_of_account_at_index(
|
let authorized_pubkey = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(first_instruction_account + 3)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(3)?,
|
||||||
)?;
|
)?;
|
||||||
if !instruction_context.is_signer(first_instruction_account + 3)? {
|
if !instruction_context.is_instruction_account_signer(3)? {
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
let custodian_pubkey = get_optional_pubkey(
|
let custodian_pubkey =
|
||||||
transaction_context,
|
get_optional_pubkey(transaction_context, instruction_context, 4, false)?;
|
||||||
instruction_context,
|
|
||||||
first_instruction_account + 4,
|
|
||||||
false,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
authorize_with_seed(
|
authorize_with_seed(
|
||||||
transaction_context,
|
transaction_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
&mut me,
|
&mut me,
|
||||||
first_instruction_account + 1,
|
1,
|
||||||
&args.authority_seed,
|
&args.authority_seed,
|
||||||
&args.authority_owner,
|
&args.authority_owner,
|
||||||
authorized_pubkey,
|
authorized_pubkey,
|
||||||
|
@ -382,12 +372,8 @@ pub fn process_instruction(
|
||||||
.feature_set
|
.feature_set
|
||||||
.is_active(&feature_set::vote_stake_checked_instructions::id())
|
.is_active(&feature_set::vote_stake_checked_instructions::id())
|
||||||
{
|
{
|
||||||
let custodian_pubkey = get_optional_pubkey(
|
let custodian_pubkey =
|
||||||
transaction_context,
|
get_optional_pubkey(transaction_context, instruction_context, 2, true)?;
|
||||||
instruction_context,
|
|
||||||
first_instruction_account + 2,
|
|
||||||
true,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let lockup = LockupArgs {
|
let lockup = LockupArgs {
|
||||||
unix_timestamp: lockup_checked.unix_timestamp,
|
unix_timestamp: lockup_checked.unix_timestamp,
|
||||||
|
@ -430,8 +416,8 @@ pub fn process_instruction(
|
||||||
transaction_context,
|
transaction_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
&mut me,
|
&mut me,
|
||||||
first_instruction_account + 1,
|
1,
|
||||||
first_instruction_account + 2,
|
2,
|
||||||
clock.epoch,
|
clock.epoch,
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -534,9 +534,10 @@ pub fn authorize_with_seed(
|
||||||
custodian: Option<&Pubkey>,
|
custodian: Option<&Pubkey>,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let mut signers = HashSet::default();
|
let mut signers = HashSet::default();
|
||||||
if instruction_context.is_signer(authority_base_index)? {
|
if instruction_context.is_instruction_account_signer(authority_base_index)? {
|
||||||
let base_pubkey = transaction_context.get_key_of_account_at_index(
|
let base_pubkey = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(authority_base_index)?,
|
instruction_context
|
||||||
|
.get_index_of_instruction_account_in_transaction(authority_base_index)?,
|
||||||
)?;
|
)?;
|
||||||
signers.insert(Pubkey::create_with_seed(
|
signers.insert(Pubkey::create_with_seed(
|
||||||
base_pubkey,
|
base_pubkey,
|
||||||
|
@ -566,8 +567,8 @@ pub fn delegate(
|
||||||
signers: &HashSet<Pubkey>,
|
signers: &HashSet<Pubkey>,
|
||||||
feature_set: &FeatureSet,
|
feature_set: &FeatureSet,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let vote_account =
|
let vote_account = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, vote_account_index)?;
|
.try_borrow_instruction_account(transaction_context, vote_account_index)?;
|
||||||
if *vote_account.get_owner() != solana_vote_program::id() {
|
if *vote_account.get_owner() != solana_vote_program::id() {
|
||||||
return Err(InstructionError::IncorrectProgramId);
|
return Err(InstructionError::IncorrectProgramId);
|
||||||
}
|
}
|
||||||
|
@ -575,8 +576,8 @@ pub fn delegate(
|
||||||
let vote_state = vote_account.get_state::<VoteStateVersions>();
|
let vote_state = vote_account.get_state::<VoteStateVersions>();
|
||||||
drop(vote_account);
|
drop(vote_account);
|
||||||
|
|
||||||
let mut stake_account =
|
let mut stake_account = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, stake_account_index)?;
|
.try_borrow_instruction_account(transaction_context, stake_account_index)?;
|
||||||
match stake_account.get_state()? {
|
match stake_account.get_state()? {
|
||||||
StakeState::Initialized(meta) => {
|
StakeState::Initialized(meta) => {
|
||||||
meta.authorized.check(signers, StakeAuthorize::Staker)?;
|
meta.authorized.check(signers, StakeAuthorize::Staker)?;
|
||||||
|
@ -653,7 +654,8 @@ pub fn split(
|
||||||
split_index: usize,
|
split_index: usize,
|
||||||
signers: &HashSet<Pubkey>,
|
signers: &HashSet<Pubkey>,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let split = instruction_context.try_borrow_account(transaction_context, split_index)?;
|
let split =
|
||||||
|
instruction_context.try_borrow_instruction_account(transaction_context, split_index)?;
|
||||||
if *split.get_owner() != id() {
|
if *split.get_owner() != id() {
|
||||||
return Err(InstructionError::IncorrectProgramId);
|
return Err(InstructionError::IncorrectProgramId);
|
||||||
}
|
}
|
||||||
|
@ -665,8 +667,8 @@ pub fn split(
|
||||||
}
|
}
|
||||||
let split_lamport_balance = split.get_lamports();
|
let split_lamport_balance = split.get_lamports();
|
||||||
drop(split);
|
drop(split);
|
||||||
let stake_account =
|
let stake_account = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, stake_account_index)?;
|
.try_borrow_instruction_account(transaction_context, stake_account_index)?;
|
||||||
if lamports > stake_account.get_lamports() {
|
if lamports > stake_account.get_lamports() {
|
||||||
return Err(InstructionError::InsufficientFunds);
|
return Err(InstructionError::InsufficientFunds);
|
||||||
}
|
}
|
||||||
|
@ -724,12 +726,12 @@ pub fn split(
|
||||||
let mut split_meta = meta;
|
let mut split_meta = meta;
|
||||||
split_meta.rent_exempt_reserve = validated_split_info.destination_rent_exempt_reserve;
|
split_meta.rent_exempt_reserve = validated_split_info.destination_rent_exempt_reserve;
|
||||||
|
|
||||||
let mut stake_account =
|
let mut stake_account = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, stake_account_index)?;
|
.try_borrow_instruction_account(transaction_context, stake_account_index)?;
|
||||||
stake_account.set_state(&StakeState::Stake(meta, stake))?;
|
stake_account.set_state(&StakeState::Stake(meta, stake))?;
|
||||||
drop(stake_account);
|
drop(stake_account);
|
||||||
let mut split =
|
let mut split = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, split_index)?;
|
.try_borrow_instruction_account(transaction_context, split_index)?;
|
||||||
split.set_state(&StakeState::Stake(split_meta, split_stake))?;
|
split.set_state(&StakeState::Stake(split_meta, split_stake))?;
|
||||||
}
|
}
|
||||||
StakeState::Initialized(meta) => {
|
StakeState::Initialized(meta) => {
|
||||||
|
@ -755,13 +757,14 @@ pub fn split(
|
||||||
)?;
|
)?;
|
||||||
let mut split_meta = meta;
|
let mut split_meta = meta;
|
||||||
split_meta.rent_exempt_reserve = validated_split_info.destination_rent_exempt_reserve;
|
split_meta.rent_exempt_reserve = validated_split_info.destination_rent_exempt_reserve;
|
||||||
let mut split =
|
let mut split = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, split_index)?;
|
.try_borrow_instruction_account(transaction_context, split_index)?;
|
||||||
split.set_state(&StakeState::Initialized(split_meta))?;
|
split.set_state(&StakeState::Initialized(split_meta))?;
|
||||||
}
|
}
|
||||||
StakeState::Uninitialized => {
|
StakeState::Uninitialized => {
|
||||||
let stake_pubkey = transaction_context.get_key_of_account_at_index(
|
let stake_pubkey = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(stake_account_index)?,
|
instruction_context
|
||||||
|
.get_index_of_instruction_account_in_transaction(stake_account_index)?,
|
||||||
)?;
|
)?;
|
||||||
if !signers.contains(stake_pubkey) {
|
if !signers.contains(stake_pubkey) {
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
|
@ -771,18 +774,19 @@ pub fn split(
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deinitialize state upon zero balance
|
// Deinitialize state upon zero balance
|
||||||
let mut stake_account =
|
let mut stake_account = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, stake_account_index)?;
|
.try_borrow_instruction_account(transaction_context, stake_account_index)?;
|
||||||
if lamports == stake_account.get_lamports() {
|
if lamports == stake_account.get_lamports() {
|
||||||
stake_account.set_state(&StakeState::Uninitialized)?;
|
stake_account.set_state(&StakeState::Uninitialized)?;
|
||||||
}
|
}
|
||||||
drop(stake_account);
|
drop(stake_account);
|
||||||
|
|
||||||
let mut split = instruction_context.try_borrow_account(transaction_context, split_index)?;
|
let mut split =
|
||||||
|
instruction_context.try_borrow_instruction_account(transaction_context, split_index)?;
|
||||||
split.checked_add_lamports(lamports)?;
|
split.checked_add_lamports(lamports)?;
|
||||||
drop(split);
|
drop(split);
|
||||||
let mut stake_account =
|
let mut stake_account = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, stake_account_index)?;
|
.try_borrow_instruction_account(transaction_context, stake_account_index)?;
|
||||||
stake_account.checked_sub_lamports(lamports)?;
|
stake_account.checked_sub_lamports(lamports)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -797,20 +801,21 @@ pub fn merge(
|
||||||
stake_history: &StakeHistory,
|
stake_history: &StakeHistory,
|
||||||
signers: &HashSet<Pubkey>,
|
signers: &HashSet<Pubkey>,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let mut source_account =
|
let mut source_account = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, source_account_index)?;
|
.try_borrow_instruction_account(transaction_context, source_account_index)?;
|
||||||
// Ensure source isn't spoofed
|
// Ensure source isn't spoofed
|
||||||
if *source_account.get_owner() != id() {
|
if *source_account.get_owner() != id() {
|
||||||
return Err(InstructionError::IncorrectProgramId);
|
return Err(InstructionError::IncorrectProgramId);
|
||||||
}
|
}
|
||||||
// Close the stake_account-reference loophole
|
// Close the stake_account-reference loophole
|
||||||
if instruction_context.get_index_in_transaction(stake_account_index)?
|
if instruction_context.get_index_of_instruction_account_in_transaction(stake_account_index)?
|
||||||
== instruction_context.get_index_in_transaction(source_account_index)?
|
== instruction_context
|
||||||
|
.get_index_of_instruction_account_in_transaction(source_account_index)?
|
||||||
{
|
{
|
||||||
return Err(InstructionError::InvalidArgument);
|
return Err(InstructionError::InvalidArgument);
|
||||||
}
|
}
|
||||||
let mut stake_account =
|
let mut stake_account = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, stake_account_index)?;
|
.try_borrow_instruction_account(transaction_context, stake_account_index)?;
|
||||||
|
|
||||||
ic_msg!(invoke_context, "Checking if destination stake is mergeable");
|
ic_msg!(invoke_context, "Checking if destination stake is mergeable");
|
||||||
let stake_merge_kind = MergeKind::get_if_mergeable(
|
let stake_merge_kind = MergeKind::get_if_mergeable(
|
||||||
|
@ -865,16 +870,17 @@ pub fn withdraw(
|
||||||
feature_set: &FeatureSet,
|
feature_set: &FeatureSet,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let withdraw_authority_pubkey = transaction_context.get_key_of_account_at_index(
|
let withdraw_authority_pubkey = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(withdraw_authority_index)?,
|
instruction_context
|
||||||
|
.get_index_of_instruction_account_in_transaction(withdraw_authority_index)?,
|
||||||
)?;
|
)?;
|
||||||
if !instruction_context.is_signer(withdraw_authority_index)? {
|
if !instruction_context.is_instruction_account_signer(withdraw_authority_index)? {
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
let mut signers = HashSet::new();
|
let mut signers = HashSet::new();
|
||||||
signers.insert(*withdraw_authority_pubkey);
|
signers.insert(*withdraw_authority_pubkey);
|
||||||
|
|
||||||
let mut stake_account =
|
let mut stake_account = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, stake_account_index)?;
|
.try_borrow_instruction_account(transaction_context, stake_account_index)?;
|
||||||
let (lockup, reserve, is_staked) = match stake_account.get_state()? {
|
let (lockup, reserve, is_staked) = match stake_account.get_state()? {
|
||||||
StakeState::Stake(meta, stake) => {
|
StakeState::Stake(meta, stake) => {
|
||||||
meta.authorized
|
meta.authorized
|
||||||
|
@ -919,10 +925,13 @@ pub fn withdraw(
|
||||||
// verify that lockup has expired or that the withdrawal is signed by
|
// verify that lockup has expired or that the withdrawal is signed by
|
||||||
// the custodian, both epoch and unix_timestamp must have passed
|
// the custodian, both epoch and unix_timestamp must have passed
|
||||||
let custodian_pubkey = if let Some(custodian_index) = custodian_index {
|
let custodian_pubkey = if let Some(custodian_index) = custodian_index {
|
||||||
if instruction_context.is_signer(custodian_index)? {
|
if instruction_context.is_instruction_account_signer(custodian_index)? {
|
||||||
Some(transaction_context.get_key_of_account_at_index(
|
Some(
|
||||||
instruction_context.get_index_in_transaction(custodian_index)?,
|
transaction_context.get_key_of_account_at_index(
|
||||||
)?)
|
instruction_context
|
||||||
|
.get_index_of_instruction_account_in_transaction(custodian_index)?,
|
||||||
|
)?,
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -955,7 +964,8 @@ pub fn withdraw(
|
||||||
|
|
||||||
stake_account.checked_sub_lamports(lamports)?;
|
stake_account.checked_sub_lamports(lamports)?;
|
||||||
drop(stake_account);
|
drop(stake_account);
|
||||||
let mut to = instruction_context.try_borrow_account(transaction_context, to_index)?;
|
let mut to =
|
||||||
|
instruction_context.try_borrow_instruction_account(transaction_context, to_index)?;
|
||||||
to.checked_add_lamports(lamports)?;
|
to.checked_add_lamports(lamports)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -969,10 +979,11 @@ pub(crate) fn deactivate_delinquent(
|
||||||
current_epoch: Epoch,
|
current_epoch: Epoch,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let delinquent_vote_account_pubkey = transaction_context.get_key_of_account_at_index(
|
let delinquent_vote_account_pubkey = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(delinquent_vote_account_index)?,
|
instruction_context
|
||||||
|
.get_index_of_instruction_account_in_transaction(delinquent_vote_account_index)?,
|
||||||
)?;
|
)?;
|
||||||
let delinquent_vote_account = instruction_context
|
let delinquent_vote_account = instruction_context
|
||||||
.try_borrow_account(transaction_context, delinquent_vote_account_index)?;
|
.try_borrow_instruction_account(transaction_context, delinquent_vote_account_index)?;
|
||||||
if *delinquent_vote_account.get_owner() != solana_vote_program::id() {
|
if *delinquent_vote_account.get_owner() != solana_vote_program::id() {
|
||||||
return Err(InstructionError::IncorrectProgramId);
|
return Err(InstructionError::IncorrectProgramId);
|
||||||
}
|
}
|
||||||
|
@ -981,7 +992,7 @@ pub(crate) fn deactivate_delinquent(
|
||||||
.convert_to_current();
|
.convert_to_current();
|
||||||
|
|
||||||
let reference_vote_account = instruction_context
|
let reference_vote_account = instruction_context
|
||||||
.try_borrow_account(transaction_context, reference_vote_account_index)?;
|
.try_borrow_instruction_account(transaction_context, reference_vote_account_index)?;
|
||||||
if *reference_vote_account.get_owner() != solana_vote_program::id() {
|
if *reference_vote_account.get_owner() != solana_vote_program::id() {
|
||||||
return Err(InstructionError::IncorrectProgramId);
|
return Err(InstructionError::IncorrectProgramId);
|
||||||
}
|
}
|
||||||
|
@ -1062,13 +1073,13 @@ fn validate_split_amount(
|
||||||
source_stake: Option<&Stake>,
|
source_stake: Option<&Stake>,
|
||||||
additional_required_lamports: u64,
|
additional_required_lamports: u64,
|
||||||
) -> Result<ValidatedSplitInfo, InstructionError> {
|
) -> Result<ValidatedSplitInfo, InstructionError> {
|
||||||
let source_account =
|
let source_account = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, source_account_index)?;
|
.try_borrow_instruction_account(transaction_context, source_account_index)?;
|
||||||
let source_lamports = source_account.get_lamports();
|
let source_lamports = source_account.get_lamports();
|
||||||
let source_data_len = source_account.get_data().len();
|
let source_data_len = source_account.get_data().len();
|
||||||
drop(source_account);
|
drop(source_account);
|
||||||
let destination_account =
|
let destination_account = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, destination_account_index)?;
|
.try_borrow_instruction_account(transaction_context, destination_account_index)?;
|
||||||
let destination_lamports = destination_account.get_lamports();
|
let destination_lamports = destination_account.get_lamports();
|
||||||
let destination_data_len = destination_account.get_data().len();
|
let destination_data_len = destination_account.get_data().len();
|
||||||
drop(destination_account);
|
drop(destination_account);
|
||||||
|
|
|
@ -81,10 +81,10 @@ fn create_accounts() -> (
|
||||||
(authority_pubkey, AccountSharedData::default()),
|
(authority_pubkey, AccountSharedData::default()),
|
||||||
];
|
];
|
||||||
let mut instruction_accounts = (0..4)
|
let mut instruction_accounts = (0..4)
|
||||||
.map(|index_in_instruction| InstructionAccount {
|
.map(|index_in_callee| InstructionAccount {
|
||||||
index_in_transaction: 1usize.saturating_add(index_in_instruction),
|
index_in_transaction: 1usize.saturating_add(index_in_callee),
|
||||||
index_in_caller: index_in_instruction,
|
index_in_caller: index_in_callee,
|
||||||
index_in_callee: index_in_instruction,
|
index_in_callee,
|
||||||
is_signer: false,
|
is_signer: false,
|
||||||
is_writable: false,
|
is_writable: false,
|
||||||
})
|
})
|
||||||
|
|
|
@ -24,7 +24,6 @@ fn process_authorize_with_seed_instruction(
|
||||||
invoke_context: &InvokeContext,
|
invoke_context: &InvokeContext,
|
||||||
instruction_context: &InstructionContext,
|
instruction_context: &InstructionContext,
|
||||||
transaction_context: &TransactionContext,
|
transaction_context: &TransactionContext,
|
||||||
first_instruction_account: usize,
|
|
||||||
vote_account: &mut BorrowedAccount,
|
vote_account: &mut BorrowedAccount,
|
||||||
new_authority: &Pubkey,
|
new_authority: &Pubkey,
|
||||||
authorization_type: VoteAuthorize,
|
authorization_type: VoteAuthorize,
|
||||||
|
@ -39,10 +38,9 @@ fn process_authorize_with_seed_instruction(
|
||||||
}
|
}
|
||||||
let clock = get_sysvar_with_account_check::clock(invoke_context, instruction_context, 1)?;
|
let clock = get_sysvar_with_account_check::clock(invoke_context, instruction_context, 1)?;
|
||||||
let mut expected_authority_keys: HashSet<Pubkey> = HashSet::default();
|
let mut expected_authority_keys: HashSet<Pubkey> = HashSet::default();
|
||||||
let authority_base_key_index = first_instruction_account + 2;
|
if instruction_context.is_instruction_account_signer(2)? {
|
||||||
if instruction_context.is_signer(authority_base_key_index)? {
|
|
||||||
let base_pubkey = transaction_context.get_key_of_account_at_index(
|
let base_pubkey = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(authority_base_key_index)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(2)?,
|
||||||
)?;
|
)?;
|
||||||
expected_authority_keys.insert(Pubkey::create_with_seed(
|
expected_authority_keys.insert(Pubkey::create_with_seed(
|
||||||
base_pubkey,
|
base_pubkey,
|
||||||
|
@ -61,7 +59,7 @@ fn process_authorize_with_seed_instruction(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_instruction(
|
pub fn process_instruction(
|
||||||
first_instruction_account: usize,
|
_first_instruction_account: usize,
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
|
@ -70,8 +68,7 @@ pub fn process_instruction(
|
||||||
|
|
||||||
trace!("process_instruction: {:?}", data);
|
trace!("process_instruction: {:?}", data);
|
||||||
|
|
||||||
let mut me =
|
let mut me = instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||||
instruction_context.try_borrow_account(transaction_context, first_instruction_account)?;
|
|
||||||
if *me.get_owner() != id() {
|
if *me.get_owner() != id() {
|
||||||
return Err(InstructionError::InvalidAccountOwner);
|
return Err(InstructionError::InvalidAccountOwner);
|
||||||
}
|
}
|
||||||
|
@ -105,7 +102,6 @@ pub fn process_instruction(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
transaction_context,
|
transaction_context,
|
||||||
first_instruction_account,
|
|
||||||
&mut me,
|
&mut me,
|
||||||
&args.new_authority,
|
&args.new_authority,
|
||||||
args.authorization_type,
|
args.authorization_type,
|
||||||
|
@ -115,18 +111,16 @@ pub fn process_instruction(
|
||||||
}
|
}
|
||||||
VoteInstruction::AuthorizeCheckedWithSeed(args) => {
|
VoteInstruction::AuthorizeCheckedWithSeed(args) => {
|
||||||
instruction_context.check_number_of_instruction_accounts(4)?;
|
instruction_context.check_number_of_instruction_accounts(4)?;
|
||||||
let new_authority_index = first_instruction_account + 3;
|
|
||||||
let new_authority = transaction_context.get_key_of_account_at_index(
|
let new_authority = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(new_authority_index)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(3)?,
|
||||||
)?;
|
)?;
|
||||||
if !instruction_context.is_signer(new_authority_index)? {
|
if !instruction_context.is_instruction_account_signer(3)? {
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
process_authorize_with_seed_instruction(
|
process_authorize_with_seed_instruction(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
transaction_context,
|
transaction_context,
|
||||||
first_instruction_account,
|
|
||||||
&mut me,
|
&mut me,
|
||||||
new_authority,
|
new_authority,
|
||||||
args.authorization_type,
|
args.authorization_type,
|
||||||
|
@ -137,7 +131,7 @@ pub fn process_instruction(
|
||||||
VoteInstruction::UpdateValidatorIdentity => {
|
VoteInstruction::UpdateValidatorIdentity => {
|
||||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||||
let node_pubkey = transaction_context.get_key_of_account_at_index(
|
let node_pubkey = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(first_instruction_account + 1)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(1)?,
|
||||||
)?;
|
)?;
|
||||||
vote_state::update_validator_identity(&mut me, node_pubkey, &signers)
|
vote_state::update_validator_identity(&mut me, node_pubkey, &signers)
|
||||||
}
|
}
|
||||||
|
@ -203,9 +197,9 @@ pub fn process_instruction(
|
||||||
vote_state::withdraw(
|
vote_state::withdraw(
|
||||||
transaction_context,
|
transaction_context,
|
||||||
instruction_context,
|
instruction_context,
|
||||||
first_instruction_account,
|
0,
|
||||||
lamports,
|
lamports,
|
||||||
first_instruction_account + 1,
|
1,
|
||||||
&signers,
|
&signers,
|
||||||
rent_sysvar.as_deref(),
|
rent_sysvar.as_deref(),
|
||||||
clock_if_feature_active.as_deref(),
|
clock_if_feature_active.as_deref(),
|
||||||
|
@ -218,9 +212,9 @@ pub fn process_instruction(
|
||||||
{
|
{
|
||||||
instruction_context.check_number_of_instruction_accounts(4)?;
|
instruction_context.check_number_of_instruction_accounts(4)?;
|
||||||
let voter_pubkey = transaction_context.get_key_of_account_at_index(
|
let voter_pubkey = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(first_instruction_account + 3)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(3)?,
|
||||||
)?;
|
)?;
|
||||||
if !instruction_context.is_signer(first_instruction_account + 3)? {
|
if !instruction_context.is_instruction_account_signer(3)? {
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
let clock =
|
let clock =
|
||||||
|
|
|
@ -1309,8 +1309,8 @@ pub fn withdraw<S: std::hash::BuildHasher>(
|
||||||
rent_sysvar: Option<&Rent>,
|
rent_sysvar: Option<&Rent>,
|
||||||
clock: Option<&Clock>,
|
clock: Option<&Clock>,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let mut vote_account =
|
let mut vote_account = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, vote_account_index)?;
|
.try_borrow_instruction_account(transaction_context, vote_account_index)?;
|
||||||
let vote_state: VoteState = vote_account
|
let vote_state: VoteState = vote_account
|
||||||
.get_state::<VoteStateVersions>()?
|
.get_state::<VoteStateVersions>()?
|
||||||
.convert_to_current();
|
.convert_to_current();
|
||||||
|
@ -1351,8 +1351,8 @@ pub fn withdraw<S: std::hash::BuildHasher>(
|
||||||
|
|
||||||
vote_account.checked_sub_lamports(lamports)?;
|
vote_account.checked_sub_lamports(lamports)?;
|
||||||
drop(vote_account);
|
drop(vote_account);
|
||||||
let mut to_account =
|
let mut to_account = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, to_account_index)?;
|
.try_borrow_instruction_account(transaction_context, to_account_index)?;
|
||||||
to_account.checked_add_lamports(lamports)?;
|
to_account.checked_add_lamports(lamports)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -770,13 +770,20 @@ pub fn inner_instructions_list_from_instruction_trace(
|
||||||
.skip(1)
|
.skip(1)
|
||||||
.map(|instruction_context| {
|
.map(|instruction_context| {
|
||||||
CompiledInstruction::new_from_raw_parts(
|
CompiledInstruction::new_from_raw_parts(
|
||||||
instruction_context.get_program_id_index() as u8,
|
instruction_context
|
||||||
instruction_context.get_instruction_data().to_vec(),
|
.get_index_of_program_account_in_transaction(
|
||||||
(instruction_context.get_number_of_program_accounts()
|
|
||||||
..instruction_context.get_number_of_accounts())
|
|
||||||
.map(|index_in_instruction| {
|
|
||||||
instruction_context
|
instruction_context
|
||||||
.get_index_in_transaction(index_in_instruction)
|
.get_number_of_program_accounts()
|
||||||
|
.saturating_sub(1),
|
||||||
|
)
|
||||||
|
.unwrap_or_default() as u8,
|
||||||
|
instruction_context.get_instruction_data().to_vec(),
|
||||||
|
(0..instruction_context.get_number_of_instruction_accounts())
|
||||||
|
.map(|instruction_account_index| {
|
||||||
|
instruction_context
|
||||||
|
.get_index_of_instruction_account_in_transaction(
|
||||||
|
instruction_account_index,
|
||||||
|
)
|
||||||
.unwrap_or_default() as u8
|
.unwrap_or_default() as u8
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
|
@ -12207,7 +12214,7 @@ pub(crate) mod tests {
|
||||||
) -> std::result::Result<(), InstructionError> {
|
) -> std::result::Result<(), InstructionError> {
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
let program_id = instruction_context.get_program_key(transaction_context)?;
|
let program_id = instruction_context.get_last_program_key(transaction_context)?;
|
||||||
if mock_vote_program_id() != *program_id {
|
if mock_vote_program_id() != *program_id {
|
||||||
return Err(InstructionError::IncorrectProgramId);
|
return Err(InstructionError::IncorrectProgramId);
|
||||||
}
|
}
|
||||||
|
@ -14108,7 +14115,7 @@ pub(crate) mod tests {
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
let instruction_context = transaction_context.get_current_instruction_context()?;
|
let instruction_context = transaction_context.get_current_instruction_context()?;
|
||||||
let _ = instruction_context
|
let _ = instruction_context
|
||||||
.try_borrow_account(transaction_context, 1)?
|
.try_borrow_program_account(transaction_context, 1)?
|
||||||
.checked_add_lamports(1);
|
.checked_add_lamports(1);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,16 +120,16 @@ impl MessageProcessor {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut instruction_accounts = Vec::with_capacity(instruction.accounts.len());
|
let mut instruction_accounts = Vec::with_capacity(instruction.accounts.len());
|
||||||
for (index_in_instruction, index_in_transaction) in
|
for (instruction_account_index, index_in_transaction) in
|
||||||
instruction.accounts.iter().enumerate()
|
instruction.accounts.iter().enumerate()
|
||||||
{
|
{
|
||||||
let index_in_callee = instruction
|
let index_in_callee = instruction
|
||||||
.accounts
|
.accounts
|
||||||
.get(0..index_in_instruction)
|
.get(0..instruction_account_index)
|
||||||
.ok_or(TransactionError::InvalidAccountIndex)?
|
.ok_or(TransactionError::InvalidAccountIndex)?
|
||||||
.iter()
|
.iter()
|
||||||
.position(|account_index| account_index == index_in_transaction)
|
.position(|account_index| account_index == index_in_transaction)
|
||||||
.unwrap_or(index_in_instruction);
|
.unwrap_or(instruction_account_index);
|
||||||
let index_in_transaction = *index_in_transaction as usize;
|
let index_in_transaction = *index_in_transaction as usize;
|
||||||
instruction_accounts.push(InstructionAccount {
|
instruction_accounts.push(InstructionAccount {
|
||||||
index_in_transaction,
|
index_in_transaction,
|
||||||
|
|
|
@ -104,8 +104,8 @@ pub fn withdraw_nonce_account(
|
||||||
transaction_context: &TransactionContext,
|
transaction_context: &TransactionContext,
|
||||||
instruction_context: &InstructionContext,
|
instruction_context: &InstructionContext,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let mut from =
|
let mut from = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, from_account_index)?;
|
.try_borrow_instruction_account(transaction_context, from_account_index)?;
|
||||||
let merge_nonce_error_into_system_error = invoke_context
|
let merge_nonce_error_into_system_error = invoke_context
|
||||||
.feature_set
|
.feature_set
|
||||||
.is_active(&feature_set::merge_nonce_error_into_system_error::id());
|
.is_active(&feature_set::merge_nonce_error_into_system_error::id());
|
||||||
|
@ -180,7 +180,8 @@ pub fn withdraw_nonce_account(
|
||||||
from.checked_sub_lamports(lamports)
|
from.checked_sub_lamports(lamports)
|
||||||
.map_err(|_| InstructionError::ArithmeticOverflow)?;
|
.map_err(|_| InstructionError::ArithmeticOverflow)?;
|
||||||
drop(from);
|
drop(from);
|
||||||
let mut to = instruction_context.try_borrow_account(transaction_context, to_account_index)?;
|
let mut to = instruction_context
|
||||||
|
.try_borrow_instruction_account(transaction_context, to_account_index)?;
|
||||||
to.checked_add_lamports(lamports)
|
to.checked_add_lamports(lamports)
|
||||||
.map_err(|_| InstructionError::ArithmeticOverflow)?;
|
.map_err(|_| InstructionError::ArithmeticOverflow)?;
|
||||||
|
|
||||||
|
@ -450,9 +451,9 @@ mod test {
|
||||||
drop(nonce_account);
|
drop(nonce_account);
|
||||||
drop(to_account);
|
drop(to_account);
|
||||||
withdraw_nonce_account(
|
withdraw_nonce_account(
|
||||||
1 + NONCE_ACCOUNT_INDEX,
|
NONCE_ACCOUNT_INDEX,
|
||||||
withdraw_lamports,
|
withdraw_lamports,
|
||||||
1 + WITHDRAW_TO_ACCOUNT_INDEX,
|
WITHDRAW_TO_ACCOUNT_INDEX,
|
||||||
&rent,
|
&rent,
|
||||||
&signers,
|
&signers,
|
||||||
&invoke_context,
|
&invoke_context,
|
||||||
|
@ -621,9 +622,9 @@ mod test {
|
||||||
drop(nonce_account);
|
drop(nonce_account);
|
||||||
drop(to_account);
|
drop(to_account);
|
||||||
withdraw_nonce_account(
|
withdraw_nonce_account(
|
||||||
1 + NONCE_ACCOUNT_INDEX,
|
NONCE_ACCOUNT_INDEX,
|
||||||
withdraw_lamports,
|
withdraw_lamports,
|
||||||
1 + WITHDRAW_TO_ACCOUNT_INDEX,
|
WITHDRAW_TO_ACCOUNT_INDEX,
|
||||||
&rent,
|
&rent,
|
||||||
&signers,
|
&signers,
|
||||||
&invoke_context,
|
&invoke_context,
|
||||||
|
@ -666,9 +667,9 @@ mod test {
|
||||||
drop(nonce_account);
|
drop(nonce_account);
|
||||||
drop(to_account);
|
drop(to_account);
|
||||||
let result = withdraw_nonce_account(
|
let result = withdraw_nonce_account(
|
||||||
1 + NONCE_ACCOUNT_INDEX,
|
NONCE_ACCOUNT_INDEX,
|
||||||
withdraw_lamports,
|
withdraw_lamports,
|
||||||
1 + WITHDRAW_TO_ACCOUNT_INDEX,
|
WITHDRAW_TO_ACCOUNT_INDEX,
|
||||||
&rent,
|
&rent,
|
||||||
&signers,
|
&signers,
|
||||||
&invoke_context,
|
&invoke_context,
|
||||||
|
@ -698,9 +699,9 @@ mod test {
|
||||||
let withdraw_lamports = nonce_account.get_lamports() + 1;
|
let withdraw_lamports = nonce_account.get_lamports() + 1;
|
||||||
drop(nonce_account);
|
drop(nonce_account);
|
||||||
let result = withdraw_nonce_account(
|
let result = withdraw_nonce_account(
|
||||||
1 + NONCE_ACCOUNT_INDEX,
|
NONCE_ACCOUNT_INDEX,
|
||||||
withdraw_lamports,
|
withdraw_lamports,
|
||||||
1 + WITHDRAW_TO_ACCOUNT_INDEX,
|
WITHDRAW_TO_ACCOUNT_INDEX,
|
||||||
&rent,
|
&rent,
|
||||||
&signers,
|
&signers,
|
||||||
&invoke_context,
|
&invoke_context,
|
||||||
|
@ -734,9 +735,9 @@ mod test {
|
||||||
drop(nonce_account);
|
drop(nonce_account);
|
||||||
drop(to_account);
|
drop(to_account);
|
||||||
withdraw_nonce_account(
|
withdraw_nonce_account(
|
||||||
1 + NONCE_ACCOUNT_INDEX,
|
NONCE_ACCOUNT_INDEX,
|
||||||
withdraw_lamports,
|
withdraw_lamports,
|
||||||
1 + WITHDRAW_TO_ACCOUNT_INDEX,
|
WITHDRAW_TO_ACCOUNT_INDEX,
|
||||||
&rent,
|
&rent,
|
||||||
&signers,
|
&signers,
|
||||||
&invoke_context,
|
&invoke_context,
|
||||||
|
@ -760,9 +761,9 @@ mod test {
|
||||||
drop(nonce_account);
|
drop(nonce_account);
|
||||||
drop(to_account);
|
drop(to_account);
|
||||||
withdraw_nonce_account(
|
withdraw_nonce_account(
|
||||||
1 + NONCE_ACCOUNT_INDEX,
|
NONCE_ACCOUNT_INDEX,
|
||||||
withdraw_lamports,
|
withdraw_lamports,
|
||||||
1 + WITHDRAW_TO_ACCOUNT_INDEX,
|
WITHDRAW_TO_ACCOUNT_INDEX,
|
||||||
&rent,
|
&rent,
|
||||||
&signers,
|
&signers,
|
||||||
&invoke_context,
|
&invoke_context,
|
||||||
|
@ -815,9 +816,9 @@ mod test {
|
||||||
drop(nonce_account);
|
drop(nonce_account);
|
||||||
drop(to_account);
|
drop(to_account);
|
||||||
withdraw_nonce_account(
|
withdraw_nonce_account(
|
||||||
1 + NONCE_ACCOUNT_INDEX,
|
NONCE_ACCOUNT_INDEX,
|
||||||
withdraw_lamports,
|
withdraw_lamports,
|
||||||
1 + WITHDRAW_TO_ACCOUNT_INDEX,
|
WITHDRAW_TO_ACCOUNT_INDEX,
|
||||||
&rent,
|
&rent,
|
||||||
&signers,
|
&signers,
|
||||||
&invoke_context,
|
&invoke_context,
|
||||||
|
@ -847,9 +848,9 @@ mod test {
|
||||||
drop(nonce_account);
|
drop(nonce_account);
|
||||||
drop(to_account);
|
drop(to_account);
|
||||||
withdraw_nonce_account(
|
withdraw_nonce_account(
|
||||||
1 + NONCE_ACCOUNT_INDEX,
|
NONCE_ACCOUNT_INDEX,
|
||||||
withdraw_lamports,
|
withdraw_lamports,
|
||||||
1 + WITHDRAW_TO_ACCOUNT_INDEX,
|
WITHDRAW_TO_ACCOUNT_INDEX,
|
||||||
&rent,
|
&rent,
|
||||||
&signers,
|
&signers,
|
||||||
&invoke_context,
|
&invoke_context,
|
||||||
|
@ -893,9 +894,9 @@ mod test {
|
||||||
drop(nonce_account);
|
drop(nonce_account);
|
||||||
drop(to_account);
|
drop(to_account);
|
||||||
let result = withdraw_nonce_account(
|
let result = withdraw_nonce_account(
|
||||||
1 + NONCE_ACCOUNT_INDEX,
|
NONCE_ACCOUNT_INDEX,
|
||||||
withdraw_lamports,
|
withdraw_lamports,
|
||||||
1 + WITHDRAW_TO_ACCOUNT_INDEX,
|
WITHDRAW_TO_ACCOUNT_INDEX,
|
||||||
&rent,
|
&rent,
|
||||||
&signers,
|
&signers,
|
||||||
&invoke_context,
|
&invoke_context,
|
||||||
|
@ -926,9 +927,9 @@ mod test {
|
||||||
let withdraw_lamports = nonce_account.get_lamports() + 1;
|
let withdraw_lamports = nonce_account.get_lamports() + 1;
|
||||||
drop(nonce_account);
|
drop(nonce_account);
|
||||||
let result = withdraw_nonce_account(
|
let result = withdraw_nonce_account(
|
||||||
1 + NONCE_ACCOUNT_INDEX,
|
NONCE_ACCOUNT_INDEX,
|
||||||
withdraw_lamports,
|
withdraw_lamports,
|
||||||
1 + WITHDRAW_TO_ACCOUNT_INDEX,
|
WITHDRAW_TO_ACCOUNT_INDEX,
|
||||||
&rent,
|
&rent,
|
||||||
&signers,
|
&signers,
|
||||||
&invoke_context,
|
&invoke_context,
|
||||||
|
@ -959,9 +960,9 @@ mod test {
|
||||||
let withdraw_lamports = 42 + 1;
|
let withdraw_lamports = 42 + 1;
|
||||||
drop(nonce_account);
|
drop(nonce_account);
|
||||||
let result = withdraw_nonce_account(
|
let result = withdraw_nonce_account(
|
||||||
1 + NONCE_ACCOUNT_INDEX,
|
NONCE_ACCOUNT_INDEX,
|
||||||
withdraw_lamports,
|
withdraw_lamports,
|
||||||
1 + WITHDRAW_TO_ACCOUNT_INDEX,
|
WITHDRAW_TO_ACCOUNT_INDEX,
|
||||||
&rent,
|
&rent,
|
||||||
&signers,
|
&signers,
|
||||||
&invoke_context,
|
&invoke_context,
|
||||||
|
@ -992,9 +993,9 @@ mod test {
|
||||||
let withdraw_lamports = u64::MAX - 54;
|
let withdraw_lamports = u64::MAX - 54;
|
||||||
drop(nonce_account);
|
drop(nonce_account);
|
||||||
let result = withdraw_nonce_account(
|
let result = withdraw_nonce_account(
|
||||||
1 + NONCE_ACCOUNT_INDEX,
|
NONCE_ACCOUNT_INDEX,
|
||||||
withdraw_lamports,
|
withdraw_lamports,
|
||||||
1 + WITHDRAW_TO_ACCOUNT_INDEX,
|
WITHDRAW_TO_ACCOUNT_INDEX,
|
||||||
&rent,
|
&rent,
|
||||||
&signers,
|
&signers,
|
||||||
&invoke_context,
|
&invoke_context,
|
||||||
|
|
|
@ -158,8 +158,8 @@ fn create_account(
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
// if it looks like the `to` account is already in use, bail
|
// if it looks like the `to` account is already in use, bail
|
||||||
{
|
{
|
||||||
let mut to =
|
let mut to = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, to_account_index)?;
|
.try_borrow_instruction_account(transaction_context, to_account_index)?;
|
||||||
if to.get_lamports() > 0 {
|
if to.get_lamports() > 0 {
|
||||||
ic_msg!(
|
ic_msg!(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
|
@ -189,8 +189,8 @@ fn transfer_verified(
|
||||||
transaction_context: &TransactionContext,
|
transaction_context: &TransactionContext,
|
||||||
instruction_context: &InstructionContext,
|
instruction_context: &InstructionContext,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let mut from =
|
let mut from = instruction_context
|
||||||
instruction_context.try_borrow_account(transaction_context, from_account_index)?;
|
.try_borrow_instruction_account(transaction_context, from_account_index)?;
|
||||||
if !from.get_data().is_empty() {
|
if !from.get_data().is_empty() {
|
||||||
ic_msg!(invoke_context, "Transfer: `from` must not carry data");
|
ic_msg!(invoke_context, "Transfer: `from` must not carry data");
|
||||||
return Err(InstructionError::InvalidArgument);
|
return Err(InstructionError::InvalidArgument);
|
||||||
|
@ -207,7 +207,8 @@ fn transfer_verified(
|
||||||
|
|
||||||
from.checked_sub_lamports(lamports)?;
|
from.checked_sub_lamports(lamports)?;
|
||||||
drop(from);
|
drop(from);
|
||||||
let mut to = instruction_context.try_borrow_account(transaction_context, to_account_index)?;
|
let mut to = instruction_context
|
||||||
|
.try_borrow_instruction_account(transaction_context, to_account_index)?;
|
||||||
to.checked_add_lamports(lamports)?;
|
to.checked_add_lamports(lamports)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -228,12 +229,13 @@ fn transfer(
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if !instruction_context.is_signer(from_account_index)? {
|
if !instruction_context.is_instruction_account_signer(from_account_index)? {
|
||||||
ic_msg!(
|
ic_msg!(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
"Transfer: `from` account {} must sign",
|
"Transfer: `from` account {} must sign",
|
||||||
transaction_context.get_key_of_account_at_index(
|
transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(from_account_index)?,
|
instruction_context
|
||||||
|
.get_index_of_instruction_account_in_transaction(from_account_index)?,
|
||||||
)?,
|
)?,
|
||||||
);
|
);
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
|
@ -268,26 +270,28 @@ fn transfer_with_seed(
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
if !instruction_context.is_signer(from_base_account_index)? {
|
if !instruction_context.is_instruction_account_signer(from_base_account_index)? {
|
||||||
ic_msg!(
|
ic_msg!(
|
||||||
invoke_context,
|
invoke_context,
|
||||||
"Transfer: 'from' account {:?} must sign",
|
"Transfer: 'from' account {:?} must sign",
|
||||||
transaction_context.get_key_of_account_at_index(
|
transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(from_base_account_index)?,
|
instruction_context
|
||||||
|
.get_index_of_instruction_account_in_transaction(from_base_account_index)?,
|
||||||
)?,
|
)?,
|
||||||
);
|
);
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
}
|
}
|
||||||
let address_from_seed = Pubkey::create_with_seed(
|
let address_from_seed = Pubkey::create_with_seed(
|
||||||
transaction_context.get_key_of_account_at_index(
|
transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(from_base_account_index)?,
|
instruction_context
|
||||||
|
.get_index_of_instruction_account_in_transaction(from_base_account_index)?,
|
||||||
)?,
|
)?,
|
||||||
from_seed,
|
from_seed,
|
||||||
from_owner,
|
from_owner,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let from_key = transaction_context.get_key_of_account_at_index(
|
let from_key = transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(from_account_index)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(from_account_index)?,
|
||||||
)?;
|
)?;
|
||||||
if *from_key != address_from_seed {
|
if *from_key != address_from_seed {
|
||||||
ic_msg!(
|
ic_msg!(
|
||||||
|
@ -310,7 +314,7 @@ fn transfer_with_seed(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_instruction(
|
pub fn process_instruction(
|
||||||
first_instruction_account: usize,
|
_first_instruction_account: usize,
|
||||||
invoke_context: &mut InvokeContext,
|
invoke_context: &mut InvokeContext,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
let transaction_context = &invoke_context.transaction_context;
|
let transaction_context = &invoke_context.transaction_context;
|
||||||
|
@ -330,14 +334,14 @@ pub fn process_instruction(
|
||||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||||
let to_address = Address::create(
|
let to_address = Address::create(
|
||||||
transaction_context.get_key_of_account_at_index(
|
transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(first_instruction_account + 1)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(1)?,
|
||||||
)?,
|
)?,
|
||||||
None,
|
None,
|
||||||
invoke_context,
|
invoke_context,
|
||||||
)?;
|
)?;
|
||||||
create_account(
|
create_account(
|
||||||
first_instruction_account,
|
0,
|
||||||
first_instruction_account + 1,
|
1,
|
||||||
&to_address,
|
&to_address,
|
||||||
lamports,
|
lamports,
|
||||||
space,
|
space,
|
||||||
|
@ -358,14 +362,14 @@ pub fn process_instruction(
|
||||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||||
let to_address = Address::create(
|
let to_address = Address::create(
|
||||||
transaction_context.get_key_of_account_at_index(
|
transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(first_instruction_account + 1)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(1)?,
|
||||||
)?,
|
)?,
|
||||||
Some((&base, &seed, &owner)),
|
Some((&base, &seed, &owner)),
|
||||||
invoke_context,
|
invoke_context,
|
||||||
)?;
|
)?;
|
||||||
create_account(
|
create_account(
|
||||||
first_instruction_account,
|
0,
|
||||||
first_instruction_account + 1,
|
1,
|
||||||
&to_address,
|
&to_address,
|
||||||
lamports,
|
lamports,
|
||||||
space,
|
space,
|
||||||
|
@ -378,11 +382,11 @@ pub fn process_instruction(
|
||||||
}
|
}
|
||||||
SystemInstruction::Assign { owner } => {
|
SystemInstruction::Assign { owner } => {
|
||||||
instruction_context.check_number_of_instruction_accounts(1)?;
|
instruction_context.check_number_of_instruction_accounts(1)?;
|
||||||
let mut account = instruction_context
|
let mut account =
|
||||||
.try_borrow_account(transaction_context, first_instruction_account)?;
|
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||||
let address = Address::create(
|
let address = Address::create(
|
||||||
transaction_context.get_key_of_account_at_index(
|
transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(first_instruction_account)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(0)?,
|
||||||
)?,
|
)?,
|
||||||
None,
|
None,
|
||||||
invoke_context,
|
invoke_context,
|
||||||
|
@ -392,8 +396,8 @@ pub fn process_instruction(
|
||||||
SystemInstruction::Transfer { lamports } => {
|
SystemInstruction::Transfer { lamports } => {
|
||||||
instruction_context.check_number_of_instruction_accounts(2)?;
|
instruction_context.check_number_of_instruction_accounts(2)?;
|
||||||
transfer(
|
transfer(
|
||||||
first_instruction_account,
|
0,
|
||||||
first_instruction_account + 1,
|
1,
|
||||||
lamports,
|
lamports,
|
||||||
invoke_context,
|
invoke_context,
|
||||||
transaction_context,
|
transaction_context,
|
||||||
|
@ -407,11 +411,11 @@ pub fn process_instruction(
|
||||||
} => {
|
} => {
|
||||||
instruction_context.check_number_of_instruction_accounts(3)?;
|
instruction_context.check_number_of_instruction_accounts(3)?;
|
||||||
transfer_with_seed(
|
transfer_with_seed(
|
||||||
first_instruction_account,
|
0,
|
||||||
first_instruction_account + 1,
|
1,
|
||||||
&from_seed,
|
&from_seed,
|
||||||
&from_owner,
|
&from_owner,
|
||||||
first_instruction_account + 2,
|
2,
|
||||||
lamports,
|
lamports,
|
||||||
invoke_context,
|
invoke_context,
|
||||||
transaction_context,
|
transaction_context,
|
||||||
|
@ -447,9 +451,9 @@ pub fn process_instruction(
|
||||||
)?;
|
)?;
|
||||||
let rent = get_sysvar_with_account_check::rent(invoke_context, instruction_context, 3)?;
|
let rent = get_sysvar_with_account_check::rent(invoke_context, instruction_context, 3)?;
|
||||||
withdraw_nonce_account(
|
withdraw_nonce_account(
|
||||||
first_instruction_account,
|
0,
|
||||||
lamports,
|
lamports,
|
||||||
first_instruction_account + 1,
|
1,
|
||||||
&rent,
|
&rent,
|
||||||
&signers,
|
&signers,
|
||||||
invoke_context,
|
invoke_context,
|
||||||
|
@ -507,11 +511,11 @@ pub fn process_instruction(
|
||||||
}
|
}
|
||||||
SystemInstruction::Allocate { space } => {
|
SystemInstruction::Allocate { space } => {
|
||||||
instruction_context.check_number_of_instruction_accounts(1)?;
|
instruction_context.check_number_of_instruction_accounts(1)?;
|
||||||
let mut account = instruction_context
|
let mut account =
|
||||||
.try_borrow_account(transaction_context, first_instruction_account)?;
|
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||||
let address = Address::create(
|
let address = Address::create(
|
||||||
transaction_context.get_key_of_account_at_index(
|
transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(first_instruction_account)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(0)?,
|
||||||
)?,
|
)?,
|
||||||
None,
|
None,
|
||||||
invoke_context,
|
invoke_context,
|
||||||
|
@ -525,11 +529,11 @@ pub fn process_instruction(
|
||||||
owner,
|
owner,
|
||||||
} => {
|
} => {
|
||||||
instruction_context.check_number_of_instruction_accounts(1)?;
|
instruction_context.check_number_of_instruction_accounts(1)?;
|
||||||
let mut account = instruction_context
|
let mut account =
|
||||||
.try_borrow_account(transaction_context, first_instruction_account)?;
|
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||||
let address = Address::create(
|
let address = Address::create(
|
||||||
transaction_context.get_key_of_account_at_index(
|
transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(first_instruction_account)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(0)?,
|
||||||
)?,
|
)?,
|
||||||
Some((&base, &seed, &owner)),
|
Some((&base, &seed, &owner)),
|
||||||
invoke_context,
|
invoke_context,
|
||||||
|
@ -545,11 +549,11 @@ pub fn process_instruction(
|
||||||
}
|
}
|
||||||
SystemInstruction::AssignWithSeed { base, seed, owner } => {
|
SystemInstruction::AssignWithSeed { base, seed, owner } => {
|
||||||
instruction_context.check_number_of_instruction_accounts(1)?;
|
instruction_context.check_number_of_instruction_accounts(1)?;
|
||||||
let mut account = instruction_context
|
let mut account =
|
||||||
.try_borrow_account(transaction_context, first_instruction_account)?;
|
instruction_context.try_borrow_instruction_account(transaction_context, 0)?;
|
||||||
let address = Address::create(
|
let address = Address::create(
|
||||||
transaction_context.get_key_of_account_at_index(
|
transaction_context.get_key_of_account_at_index(
|
||||||
instruction_context.get_index_in_transaction(first_instruction_account)?,
|
instruction_context.get_index_of_instruction_account_in_transaction(0)?,
|
||||||
)?,
|
)?,
|
||||||
Some((&base, &seed, &owner)),
|
Some((&base, &seed, &owner)),
|
||||||
invoke_context,
|
invoke_context,
|
||||||
|
|
|
@ -301,16 +301,6 @@ impl InstructionContext {
|
||||||
self.program_accounts.len()
|
self.program_accounts.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the index of the instruction's program id
|
|
||||||
pub fn get_program_id_index(&self) -> usize {
|
|
||||||
self.program_accounts.last().cloned().unwrap_or_default()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the instruction's program id
|
|
||||||
pub fn get_program_id(&self, transaction_context: &TransactionContext) -> Pubkey {
|
|
||||||
transaction_context.account_keys[self.program_accounts.last().cloned().unwrap_or_default()]
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Number of accounts in this Instruction (without program accounts)
|
/// Number of accounts in this Instruction (without program accounts)
|
||||||
pub fn get_number_of_instruction_accounts(&self) -> usize {
|
pub fn get_number_of_instruction_accounts(&self) -> usize {
|
||||||
self.instruction_accounts.len()
|
self.instruction_accounts.len()
|
||||||
|
@ -328,13 +318,6 @@ impl InstructionContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Number of accounts in this Instruction
|
|
||||||
pub fn get_number_of_accounts(&self) -> usize {
|
|
||||||
self.program_accounts
|
|
||||||
.len()
|
|
||||||
.saturating_add(self.instruction_accounts.len())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Data parameter for the programs `process_instruction` handler
|
/// Data parameter for the programs `process_instruction` handler
|
||||||
pub fn get_instruction_data(&self) -> &[u8] {
|
pub fn get_instruction_data(&self) -> &[u8] {
|
||||||
&self.instruction_data
|
&self.instruction_data
|
||||||
|
@ -353,8 +336,8 @@ impl InstructionContext {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Searches for an account by its key
|
/// Searches for an instruction account by its key
|
||||||
pub fn find_index_of_account(
|
pub fn find_index_of_instruction_account(
|
||||||
&self,
|
&self,
|
||||||
transaction_context: &TransactionContext,
|
transaction_context: &TransactionContext,
|
||||||
pubkey: &Pubkey,
|
pubkey: &Pubkey,
|
||||||
|
@ -365,82 +348,75 @@ impl InstructionContext {
|
||||||
&transaction_context.account_keys[instruction_account.index_in_transaction]
|
&transaction_context.account_keys[instruction_account.index_in_transaction]
|
||||||
== pubkey
|
== pubkey
|
||||||
})
|
})
|
||||||
.map(|index| index.saturating_add(self.program_accounts.len()))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Translates the given instruction wide index into a transaction wide index
|
/// Translates the given instruction wide program_account_index into a transaction wide index
|
||||||
pub fn get_index_in_transaction(
|
pub fn get_index_of_program_account_in_transaction(
|
||||||
&self,
|
&self,
|
||||||
index_in_instruction: usize,
|
program_account_index: usize,
|
||||||
) -> Result<usize, InstructionError> {
|
) -> Result<usize, InstructionError> {
|
||||||
if index_in_instruction < self.program_accounts.len() {
|
Ok(*self
|
||||||
Ok(self.program_accounts[index_in_instruction])
|
.program_accounts
|
||||||
} else if index_in_instruction < self.get_number_of_accounts() {
|
.get(program_account_index)
|
||||||
Ok(self.instruction_accounts
|
.ok_or(InstructionError::NotEnoughAccountKeys)?)
|
||||||
[index_in_instruction.saturating_sub(self.program_accounts.len())]
|
|
||||||
.index_in_transaction)
|
|
||||||
} else {
|
|
||||||
Err(InstructionError::NotEnoughAccountKeys)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `Some(index_in_instruction)` if this is a duplicate
|
/// Translates the given instruction wide instruction_account_index into a transaction wide index
|
||||||
/// and `None` if it is the first account with this key
|
pub fn get_index_of_instruction_account_in_transaction(
|
||||||
pub fn is_duplicate(
|
|
||||||
&self,
|
&self,
|
||||||
index_in_instruction: usize,
|
instruction_account_index: usize,
|
||||||
|
) -> Result<usize, InstructionError> {
|
||||||
|
Ok(self
|
||||||
|
.instruction_accounts
|
||||||
|
.get(instruction_account_index)
|
||||||
|
.ok_or(InstructionError::NotEnoughAccountKeys)?
|
||||||
|
.index_in_transaction)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns `Some(instruction_account_index)` if this is a duplicate
|
||||||
|
/// and `None` if it is the first account with this key
|
||||||
|
pub fn is_instruction_account_duplicate(
|
||||||
|
&self,
|
||||||
|
instruction_account_index: usize,
|
||||||
) -> Result<Option<usize>, InstructionError> {
|
) -> Result<Option<usize>, InstructionError> {
|
||||||
if index_in_instruction < self.program_accounts.len()
|
let index_in_callee = self
|
||||||
|| index_in_instruction >= self.get_number_of_accounts()
|
.instruction_accounts
|
||||||
{
|
.get(instruction_account_index)
|
||||||
Err(InstructionError::NotEnoughAccountKeys)
|
.ok_or(InstructionError::NotEnoughAccountKeys)?
|
||||||
|
.index_in_callee;
|
||||||
|
Ok(if index_in_callee == instruction_account_index {
|
||||||
|
None
|
||||||
} else {
|
} else {
|
||||||
let index_in_instruction =
|
Some(index_in_callee)
|
||||||
index_in_instruction.saturating_sub(self.program_accounts.len());
|
})
|
||||||
let index_in_callee = self.instruction_accounts[index_in_instruction].index_in_callee;
|
|
||||||
Ok(if index_in_callee == index_in_instruction {
|
|
||||||
None
|
|
||||||
} else {
|
|
||||||
Some(index_in_callee)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the key of the last program account of this Instruction
|
/// Gets the key of the last program account of this Instruction
|
||||||
pub fn get_program_key<'a, 'b: 'a>(
|
pub fn get_last_program_key<'a, 'b: 'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
transaction_context: &'b TransactionContext,
|
transaction_context: &'b TransactionContext,
|
||||||
) -> Result<&'b Pubkey, InstructionError> {
|
) -> Result<&'b Pubkey, InstructionError> {
|
||||||
let index_in_transaction =
|
let result = self
|
||||||
self.get_index_in_transaction(self.program_accounts.len().saturating_sub(1))?;
|
.get_index_of_program_account_in_transaction(
|
||||||
transaction_context.get_key_of_account_at_index(index_in_transaction)
|
self.program_accounts.len().saturating_sub(1),
|
||||||
|
)
|
||||||
|
.and_then(|index_in_transaction| {
|
||||||
|
transaction_context.get_key_of_account_at_index(index_in_transaction)
|
||||||
|
});
|
||||||
|
debug_assert!(result.is_ok());
|
||||||
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the key of an instruction account (skipping program accounts)
|
fn try_borrow_account<'a, 'b: 'a>(
|
||||||
pub fn get_instruction_account_key<'a, 'b: 'a>(
|
|
||||||
&'a self,
|
|
||||||
transaction_context: &'b TransactionContext,
|
|
||||||
instruction_account_index: usize,
|
|
||||||
) -> Result<&'b Pubkey, InstructionError> {
|
|
||||||
let index_in_transaction = self.get_index_in_transaction(
|
|
||||||
self.program_accounts
|
|
||||||
.len()
|
|
||||||
.saturating_add(instruction_account_index),
|
|
||||||
)?;
|
|
||||||
transaction_context.get_key_of_account_at_index(index_in_transaction)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Tries to borrow an account from this Instruction
|
|
||||||
pub fn try_borrow_account<'a, 'b: 'a>(
|
|
||||||
&'a self,
|
&'a self,
|
||||||
transaction_context: &'b TransactionContext,
|
transaction_context: &'b TransactionContext,
|
||||||
|
index_in_transaction: usize,
|
||||||
index_in_instruction: usize,
|
index_in_instruction: usize,
|
||||||
) -> Result<BorrowedAccount<'a>, InstructionError> {
|
) -> Result<BorrowedAccount<'a>, InstructionError> {
|
||||||
let index_in_transaction = self.get_index_in_transaction(index_in_instruction)?;
|
let account = transaction_context
|
||||||
if index_in_transaction >= transaction_context.accounts.len() {
|
.accounts
|
||||||
return Err(InstructionError::MissingAccount);
|
.get(index_in_transaction)
|
||||||
}
|
.ok_or(InstructionError::MissingAccount)?
|
||||||
let account = transaction_context.accounts[index_in_transaction]
|
|
||||||
.try_borrow_mut()
|
.try_borrow_mut()
|
||||||
.map_err(|_| InstructionError::AccountBorrowFailed)?;
|
.map_err(|_| InstructionError::AccountBorrowFailed)?;
|
||||||
Ok(BorrowedAccount {
|
Ok(BorrowedAccount {
|
||||||
|
@ -453,13 +429,30 @@ impl InstructionContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the last program account of this Instruction
|
/// Gets the last program account of this Instruction
|
||||||
pub fn try_borrow_program_account<'a, 'b: 'a>(
|
pub fn try_borrow_last_program_account<'a, 'b: 'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
transaction_context: &'b TransactionContext,
|
transaction_context: &'b TransactionContext,
|
||||||
) -> Result<BorrowedAccount<'a>, InstructionError> {
|
) -> Result<BorrowedAccount<'a>, InstructionError> {
|
||||||
self.try_borrow_account(
|
let result = self.try_borrow_program_account(
|
||||||
transaction_context,
|
transaction_context,
|
||||||
self.program_accounts.len().saturating_sub(1),
|
self.program_accounts.len().saturating_sub(1),
|
||||||
|
);
|
||||||
|
debug_assert!(result.is_ok());
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tries to borrow a program account from this Instruction
|
||||||
|
pub fn try_borrow_program_account<'a, 'b: 'a>(
|
||||||
|
&'a self,
|
||||||
|
transaction_context: &'b TransactionContext,
|
||||||
|
program_account_index: usize,
|
||||||
|
) -> Result<BorrowedAccount<'a>, InstructionError> {
|
||||||
|
let index_in_transaction =
|
||||||
|
self.get_index_of_program_account_in_transaction(program_account_index)?;
|
||||||
|
self.try_borrow_account(
|
||||||
|
transaction_context,
|
||||||
|
index_in_transaction,
|
||||||
|
program_account_index,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,39 +462,42 @@ impl InstructionContext {
|
||||||
transaction_context: &'b TransactionContext,
|
transaction_context: &'b TransactionContext,
|
||||||
instruction_account_index: usize,
|
instruction_account_index: usize,
|
||||||
) -> Result<BorrowedAccount<'a>, InstructionError> {
|
) -> Result<BorrowedAccount<'a>, InstructionError> {
|
||||||
|
let index_in_transaction =
|
||||||
|
self.get_index_of_instruction_account_in_transaction(instruction_account_index)?;
|
||||||
self.try_borrow_account(
|
self.try_borrow_account(
|
||||||
transaction_context,
|
transaction_context,
|
||||||
|
index_in_transaction,
|
||||||
self.program_accounts
|
self.program_accounts
|
||||||
.len()
|
.len()
|
||||||
.saturating_add(instruction_account_index),
|
.saturating_add(instruction_account_index),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether an account is a signer
|
/// Returns whether an instruction account is a signer
|
||||||
pub fn is_signer(&self, index_in_instruction: usize) -> Result<bool, InstructionError> {
|
pub fn is_instruction_account_signer(
|
||||||
Ok(if index_in_instruction < self.program_accounts.len() {
|
&self,
|
||||||
false
|
instruction_account_index: usize,
|
||||||
} else {
|
) -> Result<bool, InstructionError> {
|
||||||
self.instruction_accounts
|
Ok(self
|
||||||
.get(index_in_instruction.saturating_sub(self.program_accounts.len()))
|
.instruction_accounts
|
||||||
.ok_or(InstructionError::MissingAccount)?
|
.get(instruction_account_index)
|
||||||
.is_signer
|
.ok_or(InstructionError::MissingAccount)?
|
||||||
})
|
.is_signer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether an account is writable
|
/// Returns whether an instruction account is writable
|
||||||
pub fn is_writable(&self, index_in_instruction: usize) -> Result<bool, InstructionError> {
|
pub fn is_instruction_account_writable(
|
||||||
Ok(if index_in_instruction < self.program_accounts.len() {
|
&self,
|
||||||
false
|
instruction_account_index: usize,
|
||||||
} else {
|
) -> Result<bool, InstructionError> {
|
||||||
self.instruction_accounts
|
Ok(self
|
||||||
.get(index_in_instruction.saturating_sub(self.program_accounts.len()))
|
.instruction_accounts
|
||||||
.ok_or(InstructionError::MissingAccount)?
|
.get(instruction_account_index)
|
||||||
.is_writable
|
.ok_or(InstructionError::MissingAccount)?
|
||||||
})
|
.is_writable)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the set of all keys of signer accounts in this Instruction
|
/// Calculates the set of all keys of signer instruction accounts in this Instruction
|
||||||
pub fn get_signers(&self, transaction_context: &TransactionContext) -> HashSet<Pubkey> {
|
pub fn get_signers(&self, transaction_context: &TransactionContext) -> HashSet<Pubkey> {
|
||||||
let mut result = HashSet::new();
|
let mut result = HashSet::new();
|
||||||
for instruction_account in self.instruction_accounts.iter() {
|
for instruction_account in self.instruction_accounts.iter() {
|
||||||
|
@ -531,11 +527,6 @@ impl<'a> BorrowedAccount<'a> {
|
||||||
self.index_in_transaction
|
self.index_in_transaction
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the index of this account (instruction wide)
|
|
||||||
pub fn get_index_in_instruction(&self) -> usize {
|
|
||||||
self.index_in_instruction
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the public key of this account (transaction wide)
|
/// Returns the public key of this account (transaction wide)
|
||||||
pub fn get_key(&self) -> &Pubkey {
|
pub fn get_key(&self) -> &Pubkey {
|
||||||
&self.transaction_context.account_keys[self.index_in_transaction]
|
&self.transaction_context.account_keys[self.index_in_transaction]
|
||||||
|
@ -646,15 +637,27 @@ impl<'a> BorrowedAccount<'a> {
|
||||||
|
|
||||||
/// Returns whether this account is a signer (instruction wide)
|
/// Returns whether this account is a signer (instruction wide)
|
||||||
pub fn is_signer(&self) -> bool {
|
pub fn is_signer(&self) -> bool {
|
||||||
|
if self.index_in_instruction < self.instruction_context.program_accounts.len() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
self.instruction_context
|
self.instruction_context
|
||||||
.is_signer(self.index_in_instruction)
|
.is_instruction_account_signer(
|
||||||
|
self.index_in_instruction
|
||||||
|
.saturating_sub(self.instruction_context.program_accounts.len()),
|
||||||
|
)
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether this account is writable (instruction wide)
|
/// Returns whether this account is writable (instruction wide)
|
||||||
pub fn is_writable(&self) -> bool {
|
pub fn is_writable(&self) -> bool {
|
||||||
|
if self.index_in_instruction < self.instruction_context.program_accounts.len() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
self.instruction_context
|
self.instruction_context
|
||||||
.is_writable(self.index_in_instruction)
|
.is_instruction_account_writable(
|
||||||
|
self.index_in_instruction
|
||||||
|
.saturating_sub(self.instruction_context.program_accounts.len()),
|
||||||
|
)
|
||||||
.unwrap_or_default()
|
.unwrap_or_default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue