diff --git a/src/instruction.rs b/src/instruction.rs index dade54e..a265ab0 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -17,6 +17,36 @@ use crate::{ #[derive(Clone, Copy, Debug, Eq, PartialEq, ShankInstruction, TryFromPrimitive)] #[rustfmt::skip] pub enum OreInstruction { + #[account(0, name = "ore_program", desc = "Ore program")] + #[account(1, name = "signer", desc = "Signer", signer)] + #[account(2, name = "beneficiary", desc = "Beneficiary token account", writable)] + #[account(3, name = "proof", desc = "Ore proof account", writable)] + #[account(4, name = "treasury", desc = "Ore treasury account", writable)] + #[account(5, name = "treasury_tokens", desc = "Ore treasury token account", writable)] + #[account(6, name = "token_program", desc = "SPL token program")] + Claim = 0, + + #[account(0, name = "ore_program", desc = "Ore program")] + #[account(1, name = "signer", desc = "Signer", signer)] + #[account(2, name = "proof", desc = "Ore proof account", writable)] + #[account(3, name = "system_program", desc = "Solana system program")] + Close = 1, + + #[account(0, name = "ore_program", desc = "Ore program")] + #[account(1, name = "signer", desc = "Signer", signer)] + #[account(2, name = "bus", desc = "Ore bus account", writable)] + #[account(3, name = "config", desc = "Ore config account")] + #[account(4, name = "noise", desc = "Ore noise account")] + #[account(5, name = "proof", desc = "Ore proof account", writable)] + #[account(6, name = "slot_hashes", desc = "Solana slot hashes sysvar")] + Mine = 2, + + #[account(0, name = "ore_program", desc = "Ore program")] + #[account(1, name = "signer", desc = "Signer", signer)] + #[account(2, name = "proof", desc = "Ore proof account", writable)] + #[account(3, name = "system_program", desc = "Solana system program")] + Open = 3, + #[account(0, name = "ore_program", desc = "Ore program")] #[account(1, name = "signer", desc = "Signer", signer)] #[account(2, name = "bus_0", desc = "Ore bus account 0", writable)] @@ -32,37 +62,7 @@ pub enum OreInstruction { #[account(12, name = "treasury", desc = "Ore treasury account", writable)] #[account(13, name = "treasury_tokens", desc = "Ore treasury token account", writable)] #[account(14, name = "token_program", desc = "SPL token program")] - Reset = 0, - - #[account(0, name = "ore_program", desc = "Ore program")] - #[account(1, name = "signer", desc = "Signer", signer)] - #[account(2, name = "proof", desc = "Ore proof account", writable)] - #[account(3, name = "system_program", desc = "Solana system program")] - Open = 1, - - #[account(0, name = "ore_program", desc = "Ore program")] - #[account(1, name = "signer", desc = "Signer", signer)] - #[account(2, name = "proof", desc = "Ore proof account", writable)] - #[account(3, name = "system_program", desc = "Solana system program")] - Close = 2, - - #[account(0, name = "ore_program", desc = "Ore program")] - #[account(1, name = "signer", desc = "Signer", signer)] - #[account(2, name = "bus", desc = "Ore bus account", writable)] - #[account(3, name = "config", desc = "Ore config account")] - #[account(4, name = "noise", desc = "Ore noise account")] - #[account(5, name = "proof", desc = "Ore proof account", writable)] - #[account(6, name = "slot_hashes", desc = "Solana slot hashes sysvar")] - Mine = 3, - - #[account(0, name = "ore_program", desc = "Ore program")] - #[account(1, name = "signer", desc = "Signer", signer)] - #[account(2, name = "beneficiary", desc = "Beneficiary token account", writable)] - #[account(3, name = "proof", desc = "Ore proof account", writable)] - #[account(4, name = "treasury", desc = "Ore treasury account", writable)] - #[account(5, name = "treasury_tokens", desc = "Ore treasury token account", writable)] - #[account(6, name = "token_program", desc = "SPL token program")] - Claim = 4, + Reset = 4, #[account(0, name = "ore_program", desc = "Ore program")] #[account(1, name = "signer", desc = "Signer", signer)] @@ -71,6 +71,11 @@ pub enum OreInstruction { #[account(4, name = "treasury_tokens", desc = "Ore treasury token account", writable)] #[account(5, name = "token_program", desc = "SPL token program")] Stake = 5, + + #[account(0, name = "ore_program", desc = "Ore program")] + #[account(1, name = "signer", desc = "Signer", signer)] + #[account(2, name = "proof", desc = "Ore proof account", writable)] + Update = 6, #[account(0, name = "ore_program", desc = "Ore program")] #[account(1, name = "signer", desc = "Signer", signer)] @@ -80,7 +85,7 @@ pub enum OreInstruction { #[account(5, name = "mint", desc = "Ore token mint account", writable)] #[account(6, name = "mint_v1", desc = "Ore v1 token mint account", writable)] #[account(7, name = "token_program", desc = "SPL token program")] - Upgrade = 6, + Upgrade = 7, #[account(0, name = "ore_program", desc = "Ore program")] #[account(1, name = "signer", desc = "Admin signer", signer)] @@ -159,18 +164,6 @@ pub struct UpgradeArgs { pub amount: [u8; 8], } -#[repr(C)] -#[derive(Clone, Copy, Debug, Pod, Zeroable)] -pub struct UpdateAdminArgs { - pub new_admin: Pubkey, -} - -#[repr(C)] -#[derive(Clone, Copy, Debug, Pod, Zeroable)] -pub struct PauseArgs { - pub paused: u8, -} - impl_to_bytes!(InitializeArgs); impl_to_bytes!(OpenArgs); impl_to_bytes!(MineArgs); @@ -220,7 +213,7 @@ pub fn open(signer: Pubkey, miner: Pubkey) -> Instruction { program_id: crate::id(), accounts: vec![ AccountMeta::new(signer, true), - AccountMeta::new(miner, true), + AccountMeta::new_readonly(miner, false), AccountMeta::new(proof_pda.0, false), AccountMeta::new_readonly(solana_program::system_program::id(), false), AccountMeta::new_readonly(sysvar::slot_hashes::id(), false), @@ -331,7 +324,21 @@ pub fn stake(signer: Pubkey, sender: Pubkey, amount: u64) -> Instruction { } } -// build an upgrade instruction. +// Build an update instruction. +pub fn update(signer: Pubkey, miner: Pubkey) -> Instruction { + let proof = Pubkey::find_program_address(&[PROOF, signer.as_ref()], &crate::id()).0; + Instruction { + program_id: crate::id(), + accounts: vec![ + AccountMeta::new(signer, true), + AccountMeta::new_readonly(miner, false), + AccountMeta::new(proof, false), + ], + data: OreInstruction::Update.to_vec(), + } +} + +// Build an upgrade instruction. pub fn upgrade(signer: Pubkey, beneficiary: Pubkey, sender: Pubkey, amount: u64) -> Instruction { Instruction { program_id: crate::id(), diff --git a/src/lib.rs b/src/lib.rs index a5d064d..a6cf811 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -33,12 +33,13 @@ pub fn process_instruction( .ok_or(ProgramError::InvalidInstructionData)?; match OreInstruction::try_from(*tag).or(Err(ProgramError::InvalidInstructionData))? { - OreInstruction::Open => process_open(program_id, accounts, data)?, + OreInstruction::Claim => process_claim(program_id, accounts, data)?, OreInstruction::Close => process_close(program_id, accounts, data)?, OreInstruction::Mine => process_mine(program_id, accounts, data)?, - OreInstruction::Claim => process_claim(program_id, accounts, data)?, - OreInstruction::Stake => process_stake(program_id, accounts, data)?, + OreInstruction::Open => process_open(program_id, accounts, data)?, OreInstruction::Reset => process_reset(program_id, accounts, data)?, + OreInstruction::Stake => process_stake(program_id, accounts, data)?, + OreInstruction::Update => process_update(program_id, accounts, data)?, OreInstruction::Upgrade => process_upgrade(program_id, accounts, data)?, OreInstruction::Initialize => process_initialize(program_id, accounts, data)?, } diff --git a/src/loaders.rs b/src/loaders.rs index 8cc7e07..44a3ffe 100644 --- a/src/loaders.rs +++ b/src/loaders.rs @@ -319,15 +319,16 @@ pub fn load_uninitialized_pda<'a, 'info>( return Err(ProgramError::InvalidSeeds); } - load_uninitialized_account(info) + load_system_account(info, true) } /// Errors if: /// - Owner is not the system program. /// - Data is not empty. /// - Account is not writable. -pub fn load_uninitialized_account<'a, 'info>( +pub fn load_system_account<'a, 'info>( info: &'a AccountInfo<'info>, + is_writable: bool, ) -> Result<(), ProgramError> { if info.owner.ne(&system_program::id()) { return Err(ProgramError::InvalidAccountOwner); @@ -337,7 +338,7 @@ pub fn load_uninitialized_account<'a, 'info>( return Err(ProgramError::AccountAlreadyInitialized); } - if !info.is_writable { + if is_writable && !info.is_writable { return Err(ProgramError::InvalidAccountData); } diff --git a/src/processor/initialize.rs b/src/processor/initialize.rs index 7717a5f..7c0b0af 100644 --- a/src/processor/initialize.rs +++ b/src/processor/initialize.rs @@ -80,7 +80,7 @@ pub fn process_initialize<'a, 'info>( &crate::id(), )?; load_uninitialized_pda(treasury_info, &[TREASURY], args.treasury_bump, &crate::id())?; - load_uninitialized_account(treasury_tokens_info)?; + load_system_account(treasury_tokens_info, true)?; load_program(system_program, system_program::id())?; load_program(token_program, spl_token::id())?; load_program(associated_token_program, spl_associated_token_account::id())?; diff --git a/src/processor/mod.rs b/src/processor/mod.rs index 91b8fb4..5ded886 100644 --- a/src/processor/mod.rs +++ b/src/processor/mod.rs @@ -5,6 +5,7 @@ mod mine; mod open; mod reset; mod stake; +mod update; mod upgrade; pub use claim::*; @@ -14,4 +15,5 @@ pub use mine::*; pub use open::*; pub use reset::*; pub use stake::*; +pub use update::*; pub use upgrade::*; diff --git a/src/processor/open.rs b/src/processor/open.rs index f9ea4a7..3f03f61 100644 --- a/src/processor/open.rs +++ b/src/processor/open.rs @@ -43,7 +43,7 @@ pub fn process_open<'a, 'info>( return Err(ProgramError::NotEnoughAccountKeys); }; load_signer(signer)?; - load_signer(miner_info)?; + load_system_account(miner_info, false)?; load_uninitialized_pda( proof_info, &[PROOF, signer.key.as_ref()], diff --git a/src/processor/update.rs b/src/processor/update.rs new file mode 100644 index 0000000..246c6d8 --- /dev/null +++ b/src/processor/update.rs @@ -0,0 +1,28 @@ +use solana_program::{ + account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError, + pubkey::Pubkey, +}; + +use crate::{loaders::*, state::Proof, utils::AccountDeserialize}; + +/// Update changes the miner authority on a proof account. +pub fn process_update<'a, 'info>( + _program_id: &Pubkey, + accounts: &'a [AccountInfo<'info>], + _data: &[u8], +) -> ProgramResult { + // Load accounts + let [signer, miner_info, proof_info] = accounts else { + return Err(ProgramError::NotEnoughAccountKeys); + }; + load_signer(signer)?; + load_system_account(miner_info, false)?; + load_proof(proof_info, signer.key, true)?; + + // Update the proof + let mut proof_data = proof_info.data.borrow_mut(); + let proof = Proof::try_from_bytes_mut(&mut proof_data)?; + proof.miner = *miner_info.key; + + Ok(()) +}