Instruction member function (#8801)
This commit is contained in:
		| @@ -211,26 +211,6 @@ impl MessageProcessor { | ||||
|         ) | ||||
|     } | ||||
|  | ||||
|     /// Visit each unique instruction account index once | ||||
|     pub fn visit_instruction_accounts_once( | ||||
|         instruction: &CompiledInstruction, | ||||
|         work: &mut dyn FnMut(usize, usize) -> Result<(), InstructionError>, | ||||
|     ) -> Result<(), InstructionError> { | ||||
|         let mut unique_index = 0; | ||||
|         'root: for (i, account_index) in instruction.accounts.iter().enumerate() { | ||||
|             // Note: This is an O(n^2) algorithm, | ||||
|             // but performed on a very small slice and requires no heap allocations | ||||
|             for account_index_before in instruction.accounts[..i].iter() { | ||||
|                 if account_index_before == account_index { | ||||
|                     continue 'root; // skip dups | ||||
|                 } | ||||
|             } | ||||
|             work(unique_index, *account_index as usize)?; | ||||
|             unique_index += 1; | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
|  | ||||
|     /// Record the initial state of the accounts so that they can be compared | ||||
|     /// after the instruction is processed | ||||
|     pub fn create_pre_accounts( | ||||
| @@ -247,7 +227,7 @@ impl MessageProcessor { | ||||
|                 pre_accounts.push(PreAccount::new(&account, is_writable, program_id)); | ||||
|                 Ok(()) | ||||
|             }; | ||||
|             let _ = Self::visit_instruction_accounts_once(instruction, &mut work); | ||||
|             let _ = instruction.visit_each_account(&mut work); | ||||
|         } | ||||
|         pre_accounts | ||||
|     } | ||||
| @@ -292,7 +272,7 @@ impl MessageProcessor { | ||||
|                 post_sum += u128::from(account.lamports); | ||||
|                 Ok(()) | ||||
|             }; | ||||
|             Self::visit_instruction_accounts_once(instruction, &mut work)?; | ||||
|             instruction.visit_each_account(&mut work)?; | ||||
|         } | ||||
|  | ||||
|         // Verify that the total sum of all the lamports did not change | ||||
|   | ||||
| @@ -201,6 +201,26 @@ impl CompiledInstruction { | ||||
|     pub fn program_id<'a>(&self, program_ids: &'a [Pubkey]) -> &'a Pubkey { | ||||
|         &program_ids[self.program_id_index as usize] | ||||
|     } | ||||
|  | ||||
|     /// Visit each unique instruction account index once | ||||
|     pub fn visit_each_account( | ||||
|         &self, | ||||
|         work: &mut dyn FnMut(usize, usize) -> Result<(), InstructionError>, | ||||
|     ) -> Result<(), InstructionError> { | ||||
|         let mut unique_index = 0; | ||||
|         'root: for (i, account_index) in self.accounts.iter().enumerate() { | ||||
|             // Note: This is an O(n^2) algorithm, | ||||
|             // but performed on a very small slice and requires no heap allocations | ||||
|             for account_index_before in self.accounts[..i].iter() { | ||||
|                 if account_index_before == account_index { | ||||
|                     continue 'root; // skip dups | ||||
|                 } | ||||
|             } | ||||
|             work(unique_index, *account_index as usize)?; | ||||
|             unique_index += 1; | ||||
|         } | ||||
|         Ok(()) | ||||
|     } | ||||
| } | ||||
|  | ||||
| #[cfg(test)] | ||||
| @@ -236,4 +256,27 @@ mod test { | ||||
|         assert!(metas[1].is_signer); | ||||
|         assert_eq!(metas[1].pubkey, signer_pubkey); | ||||
|     } | ||||
|  | ||||
|     #[test] | ||||
|     fn test_visit_each_account() { | ||||
|         let do_work = |accounts: &[u8]| -> (usize, usize) { | ||||
|             let mut unique_total = 0; | ||||
|             let mut account_total = 0; | ||||
|             let mut work = |unique_index: usize, account_index: usize| { | ||||
|                 unique_total += unique_index; | ||||
|                 account_total += account_index; | ||||
|                 Ok(()) | ||||
|             }; | ||||
|             let instruction = CompiledInstruction::new(0, &[0], accounts.to_vec()); | ||||
|             instruction.visit_each_account(&mut work).unwrap(); | ||||
|  | ||||
|             (unique_total, account_total) | ||||
|         }; | ||||
|  | ||||
|         assert_eq!((6, 6), do_work(&[0, 1, 2, 3])); | ||||
|         assert_eq!((6, 6), do_work(&[0, 1, 1, 2, 3])); | ||||
|         assert_eq!((6, 6), do_work(&[0, 1, 2, 3, 3])); | ||||
|         assert_eq!((6, 6), do_work(&[0, 0, 1, 1, 2, 2, 3, 3])); | ||||
|         assert_eq!((0, 2), do_work(&[2, 2])); | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user