yo
im experiementing with CPI calls on devnet (running test validator locally), and I get this "Unknown program 11111111111111111111111111111111" error with An account required by the instruction is missing. here is the code for the lib and for the client:
lib:
use solana_program::{
account_info::{next_account_info, AccountInfo},
borsh::try_from_slice_unchecked,
entrypoint,
entrypoint::ProgramResult,
msg,
program::invoke_signed,
pubkey::Pubkey,
system_instruction,
sysvar::{rent::Rent, Sysvar},
};
use std::convert::TryInto;
pub mod instruction;
pub mod state;
use borsh::BorshSerialize;
use instruction::MovieInstruction;
use state::MovieAccountState;
entrypoint!(process_instruction);
pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
let instruction = MovieInstruction::unpack(instruction_data)?;
match instruction {
MovieInstruction::AddMovieReview {
title,
rating,
description,
} => add_movie_review(program_id, accounts, title, rating, description),
}
}
pub fn add_movie_review(
program_id: &Pubkey,
accounts: &[AccountInfo],
title: String,
rating: u8,
description: String,
) -> ProgramResult {
msg!("Adding movie review...");
msg!("Title: {}", title);
msg!("Rating: {}", rating);
msg!("Description: {}", description);
// Get Account iterator
let account_info_iter = &mut accounts.iter();
// Get accounts
let initializer = next_account_info(account_info_iter)?;
let pda_account = next_account_info(account_info_iter)?;
let program = next_account_info(account_info_iter)?;
// Derive PDA and check that it matches client
let (pda, bump_seed) = Pubkey::find_program_address(
&[initializer.key.as_ref(), title.as_bytes().as_ref()],
program_id,
);
// Calculate account size required
let account_len: usize = 1 + 1 + (4 + title.len()) + (4 + description.len());
// Calculate rent required
let rent = Rent::get()?;
let rent_lamports = rent.minimum_balance(account_len);
// Create the account
invoke_signed(
&system_instruction::create_account(
initializer.key,
pda_account.key,
rent_lamports,
account_len.try_into().unwrap(),
program_id,
),
&[
initializer.clone(),
pda_account.clone(),
program.clone(),
],
&[&[
initializer.key.as_ref(),
title.as_bytes().as_ref(),
&[bump_seed],
]],
)?;
msg!("PDA created: {}", pda);
msg!("unpacking state account");
let mut account_data =
try_from_slice_unchecked::<MovieAccountState>(&pda_account.data.borrow()).unwrap();
msg!("borrowed account data");
account_data.title = title;
account_data.rating = rating;
account_data.description = description;
account_data.is_initialized = true;
msg!("serializing account");
account_data.serialize(&mut &mut pda_account.data.borrow_mut()[..])?;
msg!("state account serialized");
Ok(())
}
client:
use anyhow::Result;
// use borsh::{BorshDeserialize, BorshSerialize};
use solana_client::rpc_client::RpcClient;
use solana_sdk::{
commitment_config::CommitmentConfig,
instruction::{AccountMeta, Instruction},
message::Message,
pubkey,
pubkey::Pubkey,
signature::{Keypair, Signature, Signer},
transaction::Transaction,
};
use solana_uniswapv3_core::instruction::MovieInstruction;
//pg id E4smcTetGFV1kKe328CVwKNc9bMsHSUU8bxQAz2JiJBJ
fn main() {
const MY_WALLET_ADDRESS: &str = "4aFf4bacjbusdoQVXdQTTann2reoDzUWCULPL8arsjcT";
const PROGRAM_KEYPAIR: [u8; 64] = [
53, 139, 19, 121, 208, 187, 65, 171, 215, 223, 27, 248, 72, 111, 180, 230, 83, 212, 104,
155, 54, 41, 89, 6, 57, 114, 44, 21, 180, 207, 238, 207, 230, 234, 194, 249, 239, 135, 0,
120, 164, 66, 71, 208, 154, 242, 46, 243, 123, 78, 234, 135, 91, 45, 49, 233, 127, 253,
166, 245, 82, 247, 217, 21,
];
let ACCOUNT_KEYPAIR: [u8; 64] = [
232, 79, 59, 39, 17, 25, 68, 190, 46, 152, 92, 192, 113, 2, 110, 82, 137, 115, 86, 191,
199, 163, 103, 216, 28, 79, 212, 219, 49, 50, 230, 93, 53, 23, 204, 161, 199, 145, 73, 224,
201, 175, 182, 50, 109, 80, 208, 89, 233, 123, 108, 248, 54, 206, 174, 10, 254, 244, 219,
21, 160, 184, 160, 176,
];
let rpc_url = String::from("http://127.0.0.1:8899");
let connection = RpcClient::new_with_commitment(rpc_url, CommitmentConfig::confirmed());
let pkeypair =
Keypair::from_bytes(&PROGRAM_KEYPAIR).expect("Failed to create keypair from bytes");
let akeypair =
Keypair::from_bytes(&ACCOUNT_KEYPAIR).expect("Failed to create keypair from bytes");
let signer: &dyn Signer = &akeypair;
let movie_review = MovieInstruction::AddMovieReview {
title: "title".to_string(),
rating: 5,
description: "description".to_string(),
};
let (pda_account, bump) = Pubkey::find_program_address(
&[
akeypair.pubkey().as_ref(),
"title".to_string().as_bytes().as_ref(),
],
&pkeypair.pubkey(),
);
let instruction = Instruction::new_with_borsh(
pkeypair.pubkey(),
&movie_review,
vec![
AccountMeta::new_readonly(akeypair.pubkey(), true),
AccountMeta::new(pda_account, false),
AccountMeta::new_readonly(pkeypair.pubkey(), false),
],
);
let tx_hash = submit_transaction(
&connection,
signer,
instruction,
CommitmentConfig::confirmed(),
);
// println!("hash: {:?}", tx_hash);
}
/// Submits the program instruction as per the
/// instruction definition
pub fn submit_transaction(
rpc_client: &RpcClient,
wallet_signer: &dyn Signer,
instruction: Instruction,
commitment_config: CommitmentConfig,
) -> Result<Signature, Box<dyn std::error::Error>> {
let mut transaction =
Transaction::new_unsigned(Message::new(&[instruction], Some(&wallet_signer.pubkey())));
let recent_blockhash = rpc_client
.get_latest_blockhash()
.map_err(|err| format!("error: unable to get recent blockhash: {}", err))?;
transaction
.try_sign(&vec![wallet_signer], recent_blockhash)
.map_err(|err| format!("error: failed to sign transaction: {}", err))?;
// Simulate transaction to get logs
println!("{:?}", rpc_client.simulate_transaction(&transaction));
let signature = rpc_client
.send_and_confirm_transaction_with_spinner_and_commitment(&transaction, commitment_config)
.map_err(|err| format!("error: send transaction: {}", err))?;
Ok(signature)
}
full log:
Ok(Response { context: RpcResponseContext { slot: 53211, api_version: Some(RpcApiVersion(Version { major: 1, minor: 17, patch: 25 })) }, value: RpcSimulateTransactionResult { err: Some(InstructionError(0, MissingAccount)), logs: Some(["Program GYQPuJRH45Z6rpomwj52AtoApYYgk1Pg5XT5yDjPsbuN invoke [1]", "Program log: Adding movie review...", "Program log: Title: title", "Program log: Rating: 5", "Program log: Description: description", "Unknown program 11111111111111111111111111111111", "Program GYQPuJRH45Z6rpomwj52AtoApYYgk1Pg5XT5yDjPsbuN consumed 10092 of 200000 compute units", "Program GYQPuJRH45Z6rpomwj52AtoApYYgk1Pg5XT5yDjPsbuN failed: An account required by the instruction is missing"]), accounts: None, units_consumed: Some(0), return_data: None } })
i tried to look online for people having similar issues but could only find one who had forgotten to submit the system_program account which i do submit.
thanks