Skip to content

Commit

Permalink
add new realloc ix
Browse files Browse the repository at this point in the history
  • Loading branch information
stegaBOB committed Jan 3, 2023
1 parent d36fd08 commit 071054e
Show file tree
Hide file tree
Showing 2 changed files with 99 additions and 0 deletions.
37 changes: 37 additions & 0 deletions name-service/program/src/instruction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,20 @@ pub enum NameRegistryInstruction {
/// 2. `[writeable]` Refund account
///
Delete,

/// Realloc the data of a name record.
///
/// The space change cannot be more than `MAX_PERMITTED_DATA_LENGTH` different than
/// current `space`.
///
/// Accounts expected by this instruction:
/// 0. `[writeable]` Name record to be reallocated
/// 1. `[signer]` Account owner
///
Realloc {
/// Number of bytes of memory to allocate in addition to the `NameRecordHeader`.
space: u32,
},
}

#[allow(clippy::too_many_arguments)]
Expand Down Expand Up @@ -201,3 +215,26 @@ pub fn delete(
data,
})
}

pub fn realloc(
payer_key: Pubkey,
name_service_program_id: Pubkey,
name_account_key: Pubkey,
name_owner_key: Pubkey,
space: u32,
) -> Result<Instruction, ProgramError> {
let instruction_data = NameRegistryInstruction::Realloc { space };
let data = instruction_data.try_to_vec().unwrap();
let accounts = vec![
AccountMeta::new_readonly(system_program::id(), false),
AccountMeta::new(payer_key, true),
AccountMeta::new(name_account_key, false),
AccountMeta::new_readonly(name_owner_key, true),
];

Ok(Instruction {
program_id: name_service_program_id,
accounts,
data,
})
}
62 changes: 62 additions & 0 deletions name-service/program/src/processor.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
use solana_program::rent::Rent;
use solana_program::sysvar::Sysvar;
use std::cmp::Ordering;
use {
crate::{
instruction::NameRegistryInstruction,
Expand Down Expand Up @@ -239,6 +242,61 @@ impl Processor {
Ok(())
}

fn process_realloc(accounts: &[AccountInfo], space: u32) -> ProgramResult {
let accounts_iter = &mut accounts.iter();
let system_program = next_account_info(accounts_iter)?;
let payer_account = next_account_info(accounts_iter)?;
let name_account = next_account_info(accounts_iter)?;
let name_owner = next_account_info(accounts_iter)?;

let name_record_header = NameRecordHeader::unpack_from_slice(&name_account.data.borrow())?;

// Verifications
if !name_owner.is_signer || name_record_header.owner != *name_owner.key {
msg!("The given name owner is incorrect or not a signer.");
return Err(ProgramError::InvalidArgument);
}

let new_space = NameRecordHeader::LEN + space as usize;
let required_lamports = Rent::get()?.minimum_balance(new_space);
match name_account.lamports().cmp(&required_lamports) {
Ordering::Less => {
let lamports_to_add = required_lamports - name_account.lamports();
invoke(
&system_instruction::transfer(
payer_account.key,
name_account.key,
lamports_to_add,
),
&[
payer_account.clone(),
name_account.clone(),
system_program.clone(),
],
)?;
}
Ordering::Greater => {
let lamports_to_remove = name_account.lamports() - required_lamports;
invoke(
&system_instruction::transfer(
name_account.key,
payer_account.key,
lamports_to_remove,
),
&[
name_account.clone(),
payer_account.clone(),
system_program.clone(),
],
)?;
}
Ordering::Equal => {}
}
// Max data increase is checked in realloc. No need to check here.
name_account.realloc(new_space, false)?;
Ok(())
}

pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
Expand Down Expand Up @@ -270,6 +328,10 @@ impl Processor {
msg!("Instruction: Delete Name");
Processor::process_delete(accounts)?;
}
NameRegistryInstruction::Realloc { space } => {
msg!("Instruction: Delete Name");
Processor::process_realloc(accounts, space)?;
}
}
Ok(())
}
Expand Down

0 comments on commit 071054e

Please sign in to comment.