Instruction member function (#8801)

This commit is contained in:
Jack May 2020-03-12 09:08:39 -07:00 committed by GitHub
parent f95e1ea40f
commit deaf3cb416
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 45 additions and 22 deletions

View File

@ -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

View File

@ -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]));
}
}