diff --git a/src/consts.rs b/src/consts.rs index dfca525..e1fc286 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -5,8 +5,11 @@ use solana_program::{pubkey, pubkey::Pubkey}; /// The reward rate to intialize the program with. pub const INITIAL_BASE_REWARD_RATE: u64 = 10u64.pow(3u32); -/// The spam/liveness tolerance to initialize the program with. -pub const INITIAL_TOLERANCE: i64 = 5; +/// The admin allowed to initialize the program. +pub const INITIAL_ADMIN: Pubkey = pubkey!("HBUh9g46wk2X89CvaNN15UmsznP59rh6od1h8JwYAopk"); + +/// The spam/liveness tolerance in seconds. +pub const TOLERANCE: i64 = 5; /// The minimum difficulty required of all submitted hashes. pub const MIN_DIFFICULTY: u32 = 8; // 12; diff --git a/src/error.rs b/src/error.rs index 4a1dfd3..a0fdbf9 100644 --- a/src/error.rs +++ b/src/error.rs @@ -5,26 +5,24 @@ use thiserror::Error; #[derive(Debug, Error, Clone, Copy, PartialEq, Eq, IntoPrimitive)] #[repr(u32)] pub enum OreError { - #[error("Mining is paused")] - IsPaused = 0, #[error("The epoch has ended and needs reset")] - NeedsReset = 1, + NeedsReset = 0, #[error("The provided hash is invalid")] - HashInvalid = 2, + HashInvalid = 1, #[error("The provided hash did not satisfy the minimum required difficulty")] - HashTooEasy = 3, + HashTooEasy = 2, #[error("The claim amount cannot be greater than the claimable rewards")] - ClaimTooLarge = 4, + ClaimTooLarge = 3, #[error("The clock time is invalid")] - ClockInvalid = 5, + ClockInvalid = 4, #[error("You are trying to submit too soon")] - Spam = 6, + Spam = 5, #[error("Only one hash may be validated per transaction")] - TransactionInvalid = 7, + TransactionInvalid = 6, #[error("The tolerance cannot exceed i64 max value")] - ToleranceOverflow = 8, + ToleranceOverflow = 7, #[error("The maximum supply has been reached")] - MaxSupply = 9, + MaxSupply = 8, } impl From for ProgramError { diff --git a/src/instruction.rs b/src/instruction.rs index a185ce0..0271cc7 100644 --- a/src/instruction.rs +++ b/src/instruction.rs @@ -103,21 +103,6 @@ pub enum OreInstruction { #[account(18, name = "mpl_metadata_program", desc = "Metaplex metadata program")] #[account(19, name = "rent", desc = "Solana rent sysvar")] Initialize = 100, - - #[account(0, name = "ore_program", desc = "Ore program")] - #[account(1, name = "signer", desc = "Admin signer", signer)] - #[account(2, name = "config", desc = "Ore config account", writable)] - UpdateAdmin = 101, - - #[account(0, name = "ore_program", desc = "Ore program")] - #[account(1, name = "signer", desc = "Admin signer", signer)] - #[account(2, name = "config", desc = "Ore config account", writable)] - UpdateTolerance = 102, - - #[account(0, name = "ore_program", desc = "Ore program")] - #[account(1, name = "signer", desc = "Admin signer", signer)] - #[account(2, name = "config", desc = "Ore config account", writable)] - Pause = 103, } impl OreInstruction { @@ -180,13 +165,6 @@ pub struct UpdateAdminArgs { pub new_admin: Pubkey, } -#[repr(C)] -#[derive(Clone, Copy, Debug, Pod, Zeroable)] -pub struct UpdateToleranceArgs { - pub tolerance_liveness: u64, - pub tolerance_spam: u64, -} - #[repr(C)] #[derive(Clone, Copy, Debug, Pod, Zeroable)] pub struct PauseArgs { @@ -199,9 +177,6 @@ impl_to_bytes!(MineArgs); impl_to_bytes!(ClaimArgs); impl_to_bytes!(StakeArgs); impl_to_bytes!(UpgradeArgs); -impl_to_bytes!(UpdateAdminArgs); -impl_to_bytes!(UpdateToleranceArgs); -impl_to_bytes!(PauseArgs); impl_instruction_from_bytes!(InitializeArgs); impl_instruction_from_bytes!(RegisterArgs); @@ -209,9 +184,6 @@ impl_instruction_from_bytes!(MineArgs); impl_instruction_from_bytes!(ClaimArgs); impl_instruction_from_bytes!(StakeArgs); impl_instruction_from_bytes!(UpgradeArgs); -impl_instruction_from_bytes!(UpdateAdminArgs); -impl_instruction_from_bytes!(UpdateToleranceArgs); -impl_instruction_from_bytes!(PauseArgs); /// Builds a reset instruction. pub fn reset(signer: Pubkey) -> Instruction { @@ -453,64 +425,3 @@ pub fn initialize(signer: Pubkey) -> Instruction { .concat(), } } - -/// Build an update_admin instruction. -pub fn update_admin(signer: Pubkey, new_admin: Pubkey) -> Instruction { - Instruction { - program_id: crate::id(), - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(CONFIG_ADDRESS, false), - ], - data: [ - OreInstruction::UpdateAdmin.to_vec(), - UpdateAdminArgs { new_admin }.to_bytes().to_vec(), - ] - .concat(), - } -} - -/// Build an update_tolerance instruction. -pub fn update_tolerance( - signer: Pubkey, - new_liveness_tolerance: u64, - new_spam_tolerance: u64, -) -> Instruction { - Instruction { - program_id: crate::id(), - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(CONFIG_ADDRESS, false), - ], - data: [ - OreInstruction::UpdateTolerance.to_vec(), - UpdateToleranceArgs { - tolerance_liveness: new_liveness_tolerance, - tolerance_spam: new_spam_tolerance, - } - .to_bytes() - .to_vec(), - ] - .concat(), - } -} - -/// Build a pause instruction. -pub fn pause(signer: Pubkey, paused: bool) -> Instruction { - Instruction { - program_id: crate::id(), - accounts: vec![ - AccountMeta::new(signer, true), - AccountMeta::new(CONFIG_ADDRESS, false), - ], - data: [ - OreInstruction::UpdateAdmin.to_vec(), - PauseArgs { - paused: paused as u8, - } - .to_bytes() - .to_vec(), - ] - .concat(), - } -} diff --git a/src/lib.rs b/src/lib.rs index 8114be6..e4d1e9e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -41,9 +41,6 @@ pub fn process_instruction( OreInstruction::Stake => process_stake(program_id, accounts, data)?, OreInstruction::Upgrade => process_upgrade(program_id, accounts, data)?, OreInstruction::Initialize => process_initialize(program_id, accounts, data)?, - OreInstruction::UpdateAdmin => process_update_admin(program_id, accounts, data)?, - OreInstruction::UpdateTolerance => process_update_tolerance(program_id, accounts, data)?, - OreInstruction::Pause => process_pause(program_id, accounts, data)?, } Ok(()) diff --git a/src/processor/initialize.rs b/src/processor/initialize.rs index 0651a2d..7717a5f 100644 --- a/src/processor/initialize.rs +++ b/src/processor/initialize.rs @@ -5,7 +5,6 @@ use solana_program::{ entrypoint::ProgramResult, program_error::ProgramError, program_pack::Pack, - pubkey, pubkey::Pubkey, system_program, {self, sysvar}, }; @@ -18,13 +17,10 @@ use crate::{ utils::create_pda, utils::AccountDeserialize, utils::Discriminator, - BUS, BUS_COUNT, CONFIG, INITIAL_BASE_REWARD_RATE, INITIAL_TOLERANCE, METADATA, METADATA_NAME, + BUS, BUS_COUNT, CONFIG, INITIAL_ADMIN, INITIAL_BASE_REWARD_RATE, METADATA, METADATA_NAME, METADATA_SYMBOL, METADATA_URI, MINT, MINT_ADDRESS, MINT_NOISE, TOKEN_DECIMALS, TREASURY, }; -/// The address to allow for initialization. -const AUTHORIZED_INITIALIZER: Pubkey = pubkey!("HBUh9g46wk2X89CvaNN15UmsznP59rh6od1h8JwYAopk"); - /// Initialize sets up the Ore program. Its responsibilities include: /// 1. Initialize the 8 bus accounts. /// 2. Initialize the treasury account. @@ -92,7 +88,7 @@ pub fn process_initialize<'a, 'info>( load_sysvar(rent_sysvar, sysvar::rent::id())?; // Check signer - if signer.key.ne(&AUTHORIZED_INITIALIZER) { + if signer.key.ne(&INITIAL_ADMIN) { return Err(ProgramError::MissingRequiredSignature); } @@ -142,9 +138,6 @@ pub fn process_initialize<'a, 'info>( config.admin = *signer.key; config.base_reward_rate = INITIAL_BASE_REWARD_RATE; config.last_reset_at = 0; - config.paused = 1; - config.tolerance_liveness = INITIAL_TOLERANCE; - config.tolerance_spam = INITIAL_TOLERANCE; // Initialize treasury create_pda( diff --git a/src/processor/mine.rs b/src/processor/mine.rs index 76f0667..265bc61 100644 --- a/src/processor/mine.rs +++ b/src/processor/mine.rs @@ -24,7 +24,7 @@ use crate::{ loaders::*, state::{Bus, Config, Proof}, utils::{AccountDeserialize, MineEvent}, - EPOCH_DURATION, MIN_DIFFICULTY, ONE_MINUTE, ONE_YEAR, + EPOCH_DURATION, MIN_DIFFICULTY, ONE_MINUTE, ONE_YEAR, TOLERANCE, }; /// Mine is the primary workhorse instruction of the Ore program. Its responsibilities include: @@ -66,14 +66,9 @@ pub fn process_mine<'a, 'info>( return Err(OreError::TransactionInvalid.into()); } - // Validate mining is not paused + // Validate epoch is active let config_data = config_info.data.borrow(); let config = Config::try_from_bytes(&config_data)?; - if config.paused.ne(&0) { - return Err(OreError::IsPaused.into()); - } - - // Validate epoch is active let clock = Clock::get().or(Err(ProgramError::InvalidAccountData))?; if config .last_reset_at @@ -128,14 +123,14 @@ pub fn process_mine<'a, 'info>( // Apply spam penalty let t = clock.unix_timestamp; let t_target = proof.last_hash_at.saturating_add(ONE_MINUTE); - let t_spam = t_target.saturating_sub(config.tolerance_spam); + let t_spam = t_target.saturating_sub(TOLERANCE); if t.lt(&t_spam) { sol_log("Spam penalty"); return Err(OreError::Spam.into()); } // Apply liveness penalty - let t_liveness = t_target.saturating_add(config.tolerance_liveness); + let t_liveness = t_target.saturating_add(TOLERANCE); if t.gt(&t_liveness) { reward = reward.saturating_sub( reward diff --git a/src/processor/mod.rs b/src/processor/mod.rs index 6807980..3ea9e10 100644 --- a/src/processor/mod.rs +++ b/src/processor/mod.rs @@ -2,22 +2,16 @@ mod claim; mod deregister; mod initialize; mod mine; -mod pause; mod register; mod reset; mod stake; -mod update_admin; -mod update_tolerance; mod upgrade; pub use claim::*; pub use deregister::*; pub use initialize::*; pub use mine::*; -pub use pause::*; pub use register::*; pub use reset::*; pub use stake::*; -pub use update_admin::*; -pub use update_tolerance::*; pub use upgrade::*; diff --git a/src/processor/pause.rs b/src/processor/pause.rs deleted file mode 100644 index 29e4d17..0000000 --- a/src/processor/pause.rs +++ /dev/null @@ -1,44 +0,0 @@ -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError, - pubkey::Pubkey, -}; - -use crate::{instruction::PauseArgs, loaders::*, state::Config, utils::AccountDeserialize}; - -/// Pause updates the program's pause flag. Its responsibilities include: -/// 1. Update the pause flag. -/// -/// Safety requirements: -/// - Can only succeed if the signer is the program admin. -/// - Can only succeed if the provided config is valid. -/// -/// Discussion: -/// - This should only be used to address critical contract risks and force migration to a new -/// verison (hardfork). -pub fn process_pause<'a, 'info>( - _program_id: &Pubkey, - accounts: &'a [AccountInfo<'info>], - data: &[u8], -) -> ProgramResult { - // Parse args - let args = PauseArgs::try_from_bytes(data)?; - - // Load accounts - let [signer, config_info] = accounts else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - load_signer(signer)?; - load_config(config_info, true)?; - - // Validate signer is admin - let mut config_data = config_info.data.borrow_mut(); - let config = Config::try_from_bytes_mut(&mut config_data)?; - if config.admin.ne(&signer.key) { - return Err(ProgramError::MissingRequiredSignature); - } - - // Update paused - config.paused = args.paused as u64; - - Ok(()) -} diff --git a/src/processor/reset.rs b/src/processor/reset.rs index ed385fb..3f2b924 100644 --- a/src/processor/reset.rs +++ b/src/processor/reset.rs @@ -70,14 +70,9 @@ pub fn process_reset<'a, 'info>( bus_7_info, ]; - // Validate mining is not paused + // Validate enough time has passed since last reset let mut config_data = config_info.data.borrow_mut(); let config = Config::try_from_bytes_mut(&mut config_data)?; - if config.paused.ne(&0) { - return Err(OreError::IsPaused.into()); - } - - // Validate enough time has passed since last reset let clock = Clock::get().or(Err(ProgramError::InvalidAccountData))?; if config .last_reset_at diff --git a/src/processor/update_admin.rs b/src/processor/update_admin.rs deleted file mode 100644 index 1b88148..0000000 --- a/src/processor/update_admin.rs +++ /dev/null @@ -1,54 +0,0 @@ -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError, - pubkey::Pubkey, -}; - -use crate::{instruction::UpdateAdminArgs, loaders::*, state::Config, utils::AccountDeserialize}; - -/// UpdateAdmin updates the program's admin account. Its responsibilities include: -/// 1. Update the treasury admin address. -/// -/// Safety requirements: -/// - Can only succeed if the signer is the program admin. -/// - Can only succeed if the provided treasury is valid. -/// -/// Discussion: -/// - The admin authority has one lever of power: the ability to adjust the global -/// mining difficulty. If the difficulty is too easy, miners will find hashes very quickly -/// and the bottleneck for mining will shift from local compute to Solana bandwidth. In essence, -/// if the Ore token has value and difficulty is low, mining becomes an incentivized stress -/// test for the Solana network. -/// - At the same time, if difficulty is too hard, miners will have to wait a very long period -/// of time between finding valid hashes. This will bias rewards to well-resourced miners -/// with large compute operations. Keeping a low difficulty ensures casual miners can -/// consistently earn rewards and undercuts some of the advantage of larger players. -/// - Ultimately admin authority should be delegated to a governance mechanism – either -/// democratic or futarchic – to ensure difficulty is kept at a value that represents the -/// values and interests of the ecosystem. -pub fn process_update_admin<'a, 'info>( - _program_id: &Pubkey, - accounts: &'a [AccountInfo<'info>], - data: &[u8], -) -> ProgramResult { - // Parse args - let args = UpdateAdminArgs::try_from_bytes(data)?; - - // Load accounts - let [signer, config_info] = accounts else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - load_signer(signer)?; - load_config(config_info, true)?; - - // Validate signer is admin - let mut config_data = config_info.data.borrow_mut(); - let config = Config::try_from_bytes_mut(&mut config_data)?; - if config.admin.ne(&signer.key) { - return Err(ProgramError::MissingRequiredSignature); - } - - // Update admin - config.admin = args.new_admin; - - Ok(()) -} diff --git a/src/processor/update_tolerance.rs b/src/processor/update_tolerance.rs deleted file mode 100644 index b7bd86b..0000000 --- a/src/processor/update_tolerance.rs +++ /dev/null @@ -1,54 +0,0 @@ -use solana_program::{ - account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError, - pubkey::Pubkey, -}; - -use crate::{ - error::OreError, instruction::UpdateToleranceArgs, loaders::*, state::Config, - utils::AccountDeserialize, ONE_MINUTE, -}; - -/// UpdateTolerance updates the program's tolerance settings. Its responsibilities include: -/// 1. Update the liveness tolerance. -/// 2. Update the spam tolerance. -/// -/// Safety requirements: -/// - Can only succeed if the signer is the program admin. -/// - Can only succeed if the provided config is valid. -/// - Can only succeed if the tolerances pass sanity tests. -pub fn process_update_tolerance<'a, 'info>( - _program_id: &Pubkey, - accounts: &'a [AccountInfo<'info>], - data: &[u8], -) -> ProgramResult { - // Parse args - let args = UpdateToleranceArgs::try_from_bytes(data)?; - - // Load accounts - let [signer, config_info] = accounts else { - return Err(ProgramError::NotEnoughAccountKeys); - }; - load_signer(signer)?; - load_config(config_info, true)?; - - // Validate signer is admin - let mut config_data = config_info.data.borrow_mut(); - let config = Config::try_from_bytes_mut(&mut config_data)?; - if config.admin.ne(&signer.key) { - return Err(ProgramError::MissingRequiredSignature); - } - - // Sanity checks - if args.tolerance_liveness.ge(&(ONE_MINUTE as u64)) { - return Err(OreError::ToleranceOverflow.into()); - } - if args.tolerance_spam.ge(&(ONE_MINUTE as u64)) { - return Err(OreError::ToleranceOverflow.into()); - } - - // Update tolerances - config.tolerance_liveness = args.tolerance_liveness as i64; - config.tolerance_spam = args.tolerance_spam as i64; - - Ok(()) -} diff --git a/src/state/config.rs b/src/state/config.rs index ea15408..9c79cff 100644 --- a/src/state/config.rs +++ b/src/state/config.rs @@ -19,15 +19,6 @@ pub struct Config { /// The timestamp of the last reset pub last_reset_at: i64, - - /// Is mining paused. - pub paused: u64, - - /// Seconds prior to a miner's target time during which their hashes will not be penalized. - pub tolerance_spam: i64, - - /// Seconds after a miner's target time during which their hashes will not be penalized. - pub tolerance_liveness: i64, } impl Discriminator for Config {