When calling a CPI that calls another instruction in the same program, you need to pass the program into the program, which is awkward. For example, removing this_program as an account here causes the cpi to fail with "unknown program", even though that AccountInfo is otherwise unused:
#[derive(Accounts)]
pub struct Whatever<'info> {
/// CHECK: ignore
pub whatever: AccountInfo<'info>,
/// CHECK: Validated against the crate's ID
#[account(address = crate::ID)]
pub this_program: AccountInfo<'info>,
}
pub fn handler(ctx: Context<Whatever>) -> Result<()> {
let ix = Instruction {
program_id,
accounts: vec![
AccountMeta::new_readonly(ctx.accounts.whatever.key(), false),
],
data: get_sighash(), // sha256 of "global":"functioname"
};
let account_infos = [
ctx.accounts.whatever.to_account_info(),
];
invoke(&ix, &account_infos)?;
Ok(())
}
But it's the same program, so why the requirement to pass it...