diff --git a/programs/7-bump-seed-canonicalization/insecure/src/lib.rs b/programs/7-bump-seed-canonicalization/insecure/src/lib.rs index 254f27d..83b5aea 100644 --- a/programs/7-bump-seed-canonicalization/insecure/src/lib.rs +++ b/programs/7-bump-seed-canonicalization/insecure/src/lib.rs @@ -7,12 +7,16 @@ pub mod bump_seed_canonicalization_insecure { use super::*; pub fn set_value(ctx: Context, key: u64, new_value: u64, bump: u8) -> ProgramResult { + // Derive the PDA using the provided bump seed let address = Pubkey::create_program_address(&[key.to_le_bytes().as_ref(), &[bump]], ctx.program_id)?; + + // Ensure the derived address matches the account key if address != ctx.accounts.data.key() { return Err(ProgramError::InvalidArgument); } + // Update the value stored in the account ctx.accounts.data.value = new_value; Ok(()) @@ -21,10 +25,10 @@ pub mod bump_seed_canonicalization_insecure { #[derive(Accounts)] pub struct BumpSeed<'info> { - data: Account<'info, Data>, + data: Account<'info, Data>, // The account where the data will be stored } #[account] pub struct Data { - value: u64, + value: u64, // The value stored in the account } diff --git a/programs/7-bump-seed-canonicalization/recommended/src/lib.rs b/programs/7-bump-seed-canonicalization/recommended/src/lib.rs index 59942b8..89b55be 100644 --- a/programs/7-bump-seed-canonicalization/recommended/src/lib.rs +++ b/programs/7-bump-seed-canonicalization/recommended/src/lib.rs @@ -7,6 +7,7 @@ pub mod bump_seed_canonicalization_recommended { use super::*; pub fn set_value(ctx: Context, key: u64, new_value: u64) -> ProgramResult { + // Simply update the value stored in the account, using PDA in a safe manner ctx.accounts.data.value = new_value; Ok(()) } @@ -15,21 +16,12 @@ pub mod bump_seed_canonicalization_recommended { #[derive(Accounts)] #[instruction(key: u64)] pub struct BumpSeed<'info> { - // Note a subtle pattern that is not displayed here. - // - // Usually, the usage of PDAs is broken into two parts: - // - // 1) allocation via `#[account(init, seeds = [...], bump)]` - // 2) using the account via `#[account(init, seeds = [...], bump = data.bump)] - // - // When using a PDA, it's usually recommend to store the bump seed in the - // account data, so that you can use it as demonstrated in 2), which will - // provide a more efficient check. + // Use the key to generate the PDA and store the bump seed in the account for future use. #[account(seeds = [key.to_le_bytes().as_ref()], bump)] - data: Account<'info, Data>, + data: Account<'info, Data>, // The PDA account to be validated and used } #[account] pub struct Data { - value: u64, + value: u64, // The value stored in the account } diff --git a/programs/7-bump-seed-canonicalization/secure/src/lib.rs b/programs/7-bump-seed-canonicalization/secure/src/lib.rs index b0852fa..84131fb 100644 --- a/programs/7-bump-seed-canonicalization/secure/src/lib.rs +++ b/programs/7-bump-seed-canonicalization/secure/src/lib.rs @@ -12,16 +12,20 @@ pub mod bump_seed_canonicalization_secure { new_value: u64, bump: u8, ) -> ProgramResult { + // Safely derive the PDA and the correct bump seed using find_program_address let (address, expected_bump) = Pubkey::find_program_address(&[key.to_le_bytes().as_ref()], ctx.program_id); + // Ensure the derived address matches the account key if address != ctx.accounts.data.key() { return Err(ProgramError::InvalidArgument); } + // Ensure the expected bump matches the provided bump if expected_bump != bump { return Err(ProgramError::InvalidArgument); } + // Update the value stored in the account ctx.accounts.data.value = new_value; Ok(()) } @@ -29,10 +33,10 @@ pub mod bump_seed_canonicalization_secure { #[derive(Accounts)] pub struct BumpSeed<'info> { - data: Account<'info, Data>, + data: Account<'info, Data>, // The PDA account to be validated and used } #[account] pub struct Data { - value: u64, + value: u64, // The value stored in the account }