First of all, I'm new to Solana development (came from an Ethereum background), so sorry if my question is too basic.
I'm following the SolDev
course, I'm on course state management. I have a confusion about section Lab/5. DerivePDA
. It is said:
Let’s independently derive the PDA we expect the user to have passed in
As far as I understood, the user provides the PDA for the account to be deployed at, in accounts input
, and we try to recalculate the PDA to verify its correctness. However, I see no validation in the code provided in the course.
pub fn add_movie_review(
program_id: &Pubkey,
accounts: &[AccountInfo],
title: String,
rating: u8,
description: String
) -> ProgramResult {
// 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 system_program = next_account_info(account_info_iter)?;
// Derive PDA
let (pda, bump_seed) = Pubkey::find_program_address(&[initializer.key.as_ref(), title.as_bytes().as_ref(),], program_id);
// QUESTION: why not check the calculated `pda` against `pda_account`??
// 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(), system_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(())
}
If no check is required, then why do we try to re-calculate the PDA? I can see that the code uses the provided pda_account
directly to create the new account here:
// 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(), system_program.clone()],
&[&[initializer.key.as_ref(), title.as_bytes().as_ref(), &[bump_seed]]],
)?;