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

Commit

Permalink
Instruction member function (#8801)
Browse files Browse the repository at this point in the history
  • Loading branch information
jackcmay authored Mar 12, 2020
1 parent f95e1ea commit deaf3cb
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 22 deletions.
24 changes: 2 additions & 22 deletions runtime/src/message_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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
}
Expand Down Expand Up @@ -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
Expand Down
43 changes: 43 additions & 0 deletions sdk/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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]));
}
}

0 comments on commit deaf3cb

Please sign in to comment.