Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit bf9ca98

Browse files
authored
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.
1 parent 8e3fd8a commit bf9ca98

File tree

20 files changed

+555
-544
lines changed

20 files changed

+555
-544
lines changed

program-runtime/src/invoke_context.rs

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -368,10 +368,10 @@ impl<'a> InvokeContext<'a> {
368368

369369
self.pre_accounts = Vec::with_capacity(instruction_accounts.len());
370370

371-
for (index_in_instruction, instruction_account) in
371+
for (instruction_account_index, instruction_account) in
372372
instruction_accounts.iter().enumerate()
373373
{
374-
if index_in_instruction != instruction_account.index_in_callee {
374+
if instruction_account_index != instruction_account.index_in_callee {
375375
continue; // Skip duplicate account
376376
}
377377
if instruction_account.index_in_transaction
@@ -398,7 +398,8 @@ impl<'a> InvokeContext<'a> {
398398
self.transaction_context
399399
.get_instruction_context_at(level)
400400
.and_then(|instruction_context| {
401-
instruction_context.try_borrow_program_account(self.transaction_context)
401+
instruction_context
402+
.try_borrow_last_program_account(self.transaction_context)
402403
})
403404
.map(|program_account| program_account.get_key() == program_id)
404405
.unwrap_or(false)
@@ -407,7 +408,7 @@ impl<'a> InvokeContext<'a> {
407408
.transaction_context
408409
.get_current_instruction_context()
409410
.and_then(|instruction_context| {
410-
instruction_context.try_borrow_program_account(self.transaction_context)
411+
instruction_context.try_borrow_last_program_account(self.transaction_context)
411412
})
412413
.map(|program_account| program_account.get_key() == program_id)
413414
.unwrap_or(false);
@@ -490,7 +491,7 @@ impl<'a> InvokeContext<'a> {
490491
.get_current_instruction_context()
491492
.map_err(|_| InstructionError::CallDepth)?;
492493
let program_id = instruction_context
493-
.get_program_key(self.transaction_context)
494+
.get_last_program_key(self.transaction_context)
494495
.map_err(|_| InstructionError::CallDepth)?;
495496

496497
// Verify all executable accounts have zero outstanding refs
@@ -504,8 +505,10 @@ impl<'a> InvokeContext<'a> {
504505
// Verify the per-account instruction results
505506
let (mut pre_sum, mut post_sum) = (0_u128, 0_u128);
506507
let mut pre_account_index = 0;
507-
for (index_in_instruction, instruction_account) in instruction_accounts.iter().enumerate() {
508-
if index_in_instruction != instruction_account.index_in_callee {
508+
for (instruction_account_index, instruction_account) in
509+
instruction_accounts.iter().enumerate()
510+
{
511+
if instruction_account_index != instruction_account.index_in_callee {
509512
continue; // Skip duplicate account
510513
}
511514
{
@@ -581,13 +584,15 @@ impl<'a> InvokeContext<'a> {
581584
let transaction_context = &self.transaction_context;
582585
let instruction_context = transaction_context.get_current_instruction_context()?;
583586
let program_id = instruction_context
584-
.get_program_key(transaction_context)
587+
.get_last_program_key(transaction_context)
585588
.map_err(|_| InstructionError::CallDepth)?;
586589

587590
// Verify the per-account instruction results
588591
let (mut pre_sum, mut post_sum) = (0_u128, 0_u128);
589-
for (index_in_instruction, instruction_account) in instruction_accounts.iter().enumerate() {
590-
if index_in_instruction != instruction_account.index_in_callee {
592+
for (instruction_account_index, instruction_account) in
593+
instruction_accounts.iter().enumerate()
594+
{
595+
if instruction_account_index != instruction_account.index_in_callee {
591596
continue; // Skip duplicate account
592597
}
593598
if instruction_account.index_in_transaction
@@ -599,11 +604,7 @@ impl<'a> InvokeContext<'a> {
599604
.get_account_at_index(instruction_account.index_in_transaction)?;
600605
let is_writable = if before_instruction_context_push {
601606
instruction_context
602-
.try_borrow_instruction_account(
603-
self.transaction_context,
604-
instruction_account.index_in_caller,
605-
)?
606-
.is_writable()
607+
.is_instruction_account_writable(instruction_account.index_in_caller)?
607608
} else {
608609
instruction_account.is_writable
609610
};
@@ -713,7 +714,7 @@ impl<'a> InvokeContext<'a> {
713714
let instruction_context = self.transaction_context.get_current_instruction_context()?;
714715
let mut deduplicated_instruction_accounts: Vec<InstructionAccount> = Vec::new();
715716
let mut duplicate_indicies = Vec::with_capacity(instruction.accounts.len());
716-
for (index_in_instruction, account_meta) in instruction.accounts.iter().enumerate() {
717+
for (instruction_account_index, account_meta) in instruction.accounts.iter().enumerate() {
717718
let index_in_transaction = self
718719
.transaction_context
719720
.find_index_of_account(&account_meta.pubkey)
@@ -740,10 +741,10 @@ impl<'a> InvokeContext<'a> {
740741
instruction_account.is_writable |= account_meta.is_writable;
741742
} else {
742743
let index_in_caller = instruction_context
743-
.find_index_of_account(self.transaction_context, &account_meta.pubkey)
744-
.map(|index| {
745-
index.saturating_sub(instruction_context.get_number_of_program_accounts())
746-
})
744+
.find_index_of_instruction_account(
745+
self.transaction_context,
746+
&account_meta.pubkey,
747+
)
747748
.ok_or_else(|| {
748749
ic_msg!(
749750
self,
@@ -756,7 +757,7 @@ impl<'a> InvokeContext<'a> {
756757
deduplicated_instruction_accounts.push(InstructionAccount {
757758
index_in_transaction,
758759
index_in_caller,
759-
index_in_callee: index_in_instruction,
760+
index_in_callee: instruction_account_index,
760761
is_signer: account_meta.is_signer,
761762
is_writable: account_meta.is_writable,
762763
});
@@ -804,13 +805,13 @@ impl<'a> InvokeContext<'a> {
804805
// Find and validate executables / program accounts
805806
let callee_program_id = instruction.program_id;
806807
let program_account_index = instruction_context
807-
.find_index_of_account(self.transaction_context, &callee_program_id)
808+
.find_index_of_instruction_account(self.transaction_context, &callee_program_id)
808809
.ok_or_else(|| {
809810
ic_msg!(self, "Unknown program {}", callee_program_id);
810811
InstructionError::MissingAccount
811812
})?;
812813
let borrowed_program_account = instruction_context
813-
.try_borrow_account(self.transaction_context, program_account_index)?;
814+
.try_borrow_instruction_account(self.transaction_context, program_account_index)?;
814815
if !borrowed_program_account.is_executable() {
815816
ic_msg!(self, "Account {} is not executable", callee_program_id);
816817
return Err(InstructionError::AccountNotExecutable);
@@ -952,7 +953,7 @@ impl<'a> InvokeContext<'a> {
952953

953954
let (first_instruction_account, builtin_id) = {
954955
let borrowed_root_account = instruction_context
955-
.try_borrow_account(self.transaction_context, 0)
956+
.try_borrow_program_account(self.transaction_context, 0)
956957
.map_err(|_| InstructionError::UnsupportedProgramId)?;
957958
let owner_id = borrowed_root_account.get_owner();
958959
if solana_sdk::native_loader::check_id(owner_id) {
@@ -964,7 +965,8 @@ impl<'a> InvokeContext<'a> {
964965

965966
for entry in self.builtin_programs {
966967
if entry.program_id == builtin_id {
967-
let program_id = instruction_context.get_program_id(self.transaction_context);
968+
let program_id =
969+
*instruction_context.get_last_program_key(self.transaction_context)?;
968970
if builtin_id == program_id {
969971
let logger = self.get_log_collector();
970972
stable_log::program_invoke(&logger, &program_id, self.get_stack_height());
@@ -1123,19 +1125,19 @@ pub fn prepare_mock_invoke_context(
11231125
) -> MockInvokeContextPreparation {
11241126
let mut instruction_accounts: Vec<InstructionAccount> =
11251127
Vec::with_capacity(instruction_account_metas.len());
1126-
for (index_in_instruction, account_meta) in instruction_account_metas.iter().enumerate() {
1128+
for (instruction_account_index, account_meta) in instruction_account_metas.iter().enumerate() {
11271129
let index_in_transaction = transaction_accounts
11281130
.iter()
11291131
.position(|(key, _account)| *key == account_meta.pubkey)
11301132
.unwrap_or(transaction_accounts.len());
11311133
let index_in_callee = instruction_accounts
1132-
.get(0..index_in_instruction)
1134+
.get(0..instruction_account_index)
11331135
.unwrap()
11341136
.iter()
11351137
.position(|instruction_account| {
11361138
instruction_account.index_in_transaction == index_in_transaction
11371139
})
1138-
.unwrap_or(index_in_instruction);
1140+
.unwrap_or(instruction_account_index);
11391141
instruction_accounts.push(InstructionAccount {
11401142
index_in_transaction,
11411143
index_in_caller: index_in_transaction,
@@ -1295,7 +1297,7 @@ mod tests {
12951297
let transaction_context = &invoke_context.transaction_context;
12961298
let instruction_context = transaction_context.get_current_instruction_context()?;
12971299
let instruction_data = instruction_context.get_instruction_data();
1298-
let program_id = instruction_context.get_program_key(transaction_context)?;
1300+
let program_id = instruction_context.get_last_program_key(transaction_context)?;
12991301
assert_eq!(
13001302
program_id,
13011303
instruction_context
@@ -1528,12 +1530,12 @@ mod tests {
15281530
AccountMeta::new_readonly(accounts.get(2).unwrap().0, false),
15291531
];
15301532
let instruction_accounts = (0..4)
1531-
.map(|index_in_instruction| InstructionAccount {
1532-
index_in_transaction: index_in_instruction,
1533-
index_in_caller: index_in_instruction,
1534-
index_in_callee: index_in_instruction,
1533+
.map(|instruction_account_index| InstructionAccount {
1534+
index_in_transaction: instruction_account_index,
1535+
index_in_caller: instruction_account_index,
1536+
index_in_callee: instruction_account_index,
15351537
is_signer: false,
1536-
is_writable: index_in_instruction < 2,
1538+
is_writable: instruction_account_index < 2,
15371539
})
15381540
.collect::<Vec<_>>();
15391541
let mut transaction_context = TransactionContext::new(accounts, 2, 8);

program-runtime/src/sysvar_cache.rs

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -186,10 +186,9 @@ pub mod get_sysvar_with_account_check {
186186
instruction_context: &InstructionContext,
187187
instruction_account_index: usize,
188188
) -> Result<(), InstructionError> {
189-
if !S::check_id(
190-
instruction_context
191-
.get_instruction_account_key(transaction_context, instruction_account_index)?,
192-
) {
189+
let index_in_transaction = instruction_context
190+
.get_index_of_instruction_account_in_transaction(instruction_account_index)?;
191+
if !S::check_id(transaction_context.get_key_of_account_at_index(index_in_transaction)?) {
193192
return Err(InstructionError::InvalidArgument);
194193
}
195194
Ok(())
@@ -198,38 +197,38 @@ pub mod get_sysvar_with_account_check {
198197
pub fn clock(
199198
invoke_context: &InvokeContext,
200199
instruction_context: &InstructionContext,
201-
index_in_instruction: usize,
200+
instruction_account_index: usize,
202201
) -> Result<Arc<Clock>, InstructionError> {
203202
check_sysvar_account::<Clock>(
204203
invoke_context.transaction_context,
205204
instruction_context,
206-
index_in_instruction,
205+
instruction_account_index,
207206
)?;
208207
invoke_context.get_sysvar_cache().get_clock()
209208
}
210209

211210
pub fn rent(
212211
invoke_context: &InvokeContext,
213212
instruction_context: &InstructionContext,
214-
index_in_instruction: usize,
213+
instruction_account_index: usize,
215214
) -> Result<Arc<Rent>, InstructionError> {
216215
check_sysvar_account::<Rent>(
217216
invoke_context.transaction_context,
218217
instruction_context,
219-
index_in_instruction,
218+
instruction_account_index,
220219
)?;
221220
invoke_context.get_sysvar_cache().get_rent()
222221
}
223222

224223
pub fn slot_hashes(
225224
invoke_context: &InvokeContext,
226225
instruction_context: &InstructionContext,
227-
index_in_instruction: usize,
226+
instruction_account_index: usize,
228227
) -> Result<Arc<SlotHashes>, InstructionError> {
229228
check_sysvar_account::<SlotHashes>(
230229
invoke_context.transaction_context,
231230
instruction_context,
232-
index_in_instruction,
231+
instruction_account_index,
233232
)?;
234233
invoke_context.get_sysvar_cache().get_slot_hashes()
235234
}
@@ -238,25 +237,25 @@ pub mod get_sysvar_with_account_check {
238237
pub fn recent_blockhashes(
239238
invoke_context: &InvokeContext,
240239
instruction_context: &InstructionContext,
241-
index_in_instruction: usize,
240+
instruction_account_index: usize,
242241
) -> Result<Arc<RecentBlockhashes>, InstructionError> {
243242
check_sysvar_account::<RecentBlockhashes>(
244243
invoke_context.transaction_context,
245244
instruction_context,
246-
index_in_instruction,
245+
instruction_account_index,
247246
)?;
248247
invoke_context.get_sysvar_cache().get_recent_blockhashes()
249248
}
250249

251250
pub fn stake_history(
252251
invoke_context: &InvokeContext,
253252
instruction_context: &InstructionContext,
254-
index_in_instruction: usize,
253+
instruction_account_index: usize,
255254
) -> Result<Arc<StakeHistory>, InstructionError> {
256255
check_sysvar_account::<StakeHistory>(
257256
invoke_context.transaction_context,
258257
instruction_context,
259-
index_in_instruction,
258+
instruction_account_index,
260259
)?;
261260
invoke_context.get_sysvar_cache().get_stake_history()
262261
}

program-test/src/lib.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -101,26 +101,25 @@ pub fn builtin_process_instruction(
101101
let transaction_context = &invoke_context.transaction_context;
102102
let instruction_context = transaction_context.get_current_instruction_context()?;
103103
let instruction_data = instruction_context.get_instruction_data();
104-
let indices_in_instruction = instruction_context.get_number_of_program_accounts()
105-
..instruction_context.get_number_of_accounts();
104+
let instruction_account_indices = 0..instruction_context.get_number_of_instruction_accounts();
106105

107106
let log_collector = invoke_context.get_log_collector();
108-
let program_id = instruction_context.get_program_key(transaction_context)?;
107+
let program_id = instruction_context.get_last_program_key(transaction_context)?;
109108
stable_log::program_invoke(
110109
&log_collector,
111110
program_id,
112111
invoke_context.get_stack_height(),
113112
);
114113

115114
// Copy indices_in_instruction into a HashSet to ensure there are no duplicates
116-
let deduplicated_indices: HashSet<usize> = indices_in_instruction.clone().collect();
115+
let deduplicated_indices: HashSet<usize> = instruction_account_indices.clone().collect();
117116

118117
// Create copies of the accounts
119118
let mut account_copies = deduplicated_indices
120119
.iter()
121-
.map(|index_in_instruction| {
120+
.map(|instruction_account_index| {
122121
let borrowed_account = instruction_context
123-
.try_borrow_account(transaction_context, *index_in_instruction)?;
122+
.try_borrow_instruction_account(transaction_context, *instruction_account_index)?;
124123
Ok((
125124
*borrowed_account.get_key(),
126125
*borrowed_account.get_owner(),
@@ -144,15 +143,15 @@ pub fn builtin_process_instruction(
144143
.collect();
145144

146145
// Create AccountInfos
147-
let account_infos = indices_in_instruction
148-
.map(|index_in_instruction| {
146+
let account_infos = instruction_account_indices
147+
.map(|instruction_account_index| {
149148
let account_copy_index = deduplicated_indices
150149
.iter()
151-
.position(|index| *index == index_in_instruction)
150+
.position(|index| *index == instruction_account_index)
152151
.unwrap();
153152
let (key, owner, lamports, data) = &account_refs[account_copy_index];
154153
let borrowed_account = instruction_context
155-
.try_borrow_account(transaction_context, index_in_instruction)?;
154+
.try_borrow_instruction_account(transaction_context, instruction_account_index)?;
156155
Ok(AccountInfo {
157156
key,
158157
is_signer: borrowed_account.is_signer(),
@@ -175,12 +174,12 @@ pub fn builtin_process_instruction(
175174
stable_log::program_success(&log_collector, program_id);
176175

177176
// Commit AccountInfo changes back into KeyedAccounts
178-
for (index_in_instruction, (_key, _owner, lamports, data)) in deduplicated_indices
177+
for (instruction_account_index, (_key, _owner, lamports, data)) in deduplicated_indices
179178
.into_iter()
180179
.zip(account_copies.into_iter())
181180
{
182-
let mut borrowed_account =
183-
instruction_context.try_borrow_account(transaction_context, index_in_instruction)?;
181+
let mut borrowed_account = instruction_context
182+
.try_borrow_instruction_account(transaction_context, instruction_account_index)?;
184183
if borrowed_account.is_writable() {
185184
borrowed_account.set_lamports(lamports)?;
186185
borrowed_account.set_data(&data)?;
@@ -253,7 +252,7 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
253252
.get_current_instruction_context()
254253
.unwrap();
255254
let caller = instruction_context
256-
.get_program_key(transaction_context)
255+
.get_last_program_key(transaction_context)
257256
.unwrap();
258257

259258
stable_log::program_invoke(
@@ -379,7 +378,7 @@ impl solana_sdk::program_stubs::SyscallStubs for SyscallStubs {
379378
.get_current_instruction_context()
380379
.unwrap();
381380
let caller = *instruction_context
382-
.get_program_key(transaction_context)
381+
.get_last_program_key(transaction_context)
383382
.unwrap();
384383
transaction_context
385384
.set_return_data(caller, data.to_vec())

0 commit comments

Comments
 (0)