ore-program 1.2.1

Ore is a digital currency you can mine from anywhere, at home or on your phone.
Documentation
use solana_program::{
    account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError,
    pubkey::Pubkey,
};

use crate::{
    instruction::UpdateDifficultyArgs, loaders::*, state::Treasury, utils::AccountDeserialize,
};

/// UpdateDifficulty updates the program's global difficulty value. Its responsibilities include:
/// 1. Update the mining difficulty.
///
/// Safety requirements:
/// - Can only succeed if the signer is the program admin.
/// - Can only succeed if the provided treasury is valid.
///
/// Discussion:
/// - Ore subdivides into 1 billion indivisible atomic units. Therefore if global hashpower
///   were to increase to the point where >1B valid hashes were submitted to the protocol for
///   validation per epoch, the Ore inflation rate could be pushed above the 1 ORE / min target.
/// - The strict limits on bus reward counters guarantee inflation can never exceed 2 ORE / min,
///   but it is the responsibility of the admin to adjust mining difficulty if needed to maintain
///   the 1 ORE / min target average.
/// - It is worth noting that Solana today processes well below 1 million real TPS or
///   (60 * 1,000,000) = 60,000,000 transactions per minute. Even if every transaction on Solana
///   were a mine operation, this would still be two orders of magnitude below the boundary
///   condition where Ore inflation targets would be challenged. So in practice, Solana is likely
///   to reach its network saturation point long before Ore ever hits its theoretical limits.
pub fn process_update_difficulty<'a, 'info>(
    _program_id: &Pubkey,
    accounts: &'a [AccountInfo<'info>],
    data: &[u8],
) -> ProgramResult {
    // Parse args
    let args = UpdateDifficultyArgs::try_from_bytes(data)?;

    // Load accounts
    let [signer, treasury_info] = accounts else {
        return Err(ProgramError::NotEnoughAccountKeys);
    };
    load_signer(signer)?;
    load_treasury(treasury_info, true)?;

    // Validate signer is admin
    let mut treasury_data = treasury_info.data.borrow_mut();
    let treasury = Treasury::try_from_bytes_mut(&mut treasury_data)?;
    if treasury.admin.ne(&signer.key) {
        return Err(ProgramError::MissingRequiredSignature);
    }

    // Update admin
    treasury.difficulty = args.new_difficulty;

    Ok(())
}