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]]], )?;