Instruction member function (#8801)
This commit is contained in:
parent
f95e1ea40f
commit
deaf3cb416
|
@ -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]));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue