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 |     /// Record the initial state of the accounts so that they can be compared | ||||||
|     /// after the instruction is processed |     /// after the instruction is processed | ||||||
|     pub fn create_pre_accounts( |     pub fn create_pre_accounts( | ||||||
| @@ -247,7 +227,7 @@ impl MessageProcessor { | |||||||
|                 pre_accounts.push(PreAccount::new(&account, is_writable, program_id)); |                 pre_accounts.push(PreAccount::new(&account, is_writable, program_id)); | ||||||
|                 Ok(()) |                 Ok(()) | ||||||
|             }; |             }; | ||||||
|             let _ = Self::visit_instruction_accounts_once(instruction, &mut work); |             let _ = instruction.visit_each_account(&mut work); | ||||||
|         } |         } | ||||||
|         pre_accounts |         pre_accounts | ||||||
|     } |     } | ||||||
| @@ -292,7 +272,7 @@ impl MessageProcessor { | |||||||
|                 post_sum += u128::from(account.lamports); |                 post_sum += u128::from(account.lamports); | ||||||
|                 Ok(()) |                 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 |         // 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 { |     pub fn program_id<'a>(&self, program_ids: &'a [Pubkey]) -> &'a Pubkey { | ||||||
|         &program_ids[self.program_id_index as usize] |         &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)] | #[cfg(test)] | ||||||
| @@ -236,4 +256,27 @@ mod test { | |||||||
|         assert!(metas[1].is_signer); |         assert!(metas[1].is_signer); | ||||||
|         assert_eq!(metas[1].pubkey, signer_pubkey); |         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