groundwork for pick your difficulty

This commit is contained in:
Hardhat Chad
2024-04-16 03:26:40 +00:00
parent 9122429140
commit 3a109e7a11
23 changed files with 2687 additions and 2654 deletions

View File

@@ -48,11 +48,11 @@ pub fn process_claim<'a, 'info>(
)?;
load_program(token_program, spl_token::id())?;
// Update claimable amount
// Update miner balance
let mut proof_data = proof_info.data.borrow_mut();
let proof = Proof::try_from_bytes_mut(&mut proof_data)?;
proof.claimable_rewards = proof
.claimable_rewards
proof.balance = proof
.balance
.checked_sub(amount)
.ok_or(OreError::ClaimTooLarge)?;

View File

@@ -13,11 +13,11 @@ use spl_token::state::Mint;
use crate::{
instruction::*,
loaders::*,
state::{Bus, Treasury},
state::{Bus, Config, Treasury},
utils::create_pda,
utils::AccountDeserialize,
utils::Discriminator,
BUS, BUS_COUNT, INITIAL_DIFFICULTY, INITIAL_REWARD_RATE, METADATA, METADATA_NAME,
BUS, BUS_COUNT, CONFIG, INITIAL_DIFFICULTY, INITIAL_REWARD_RATE, METADATA, METADATA_NAME,
METADATA_SYMBOL, METADATA_URI, MINT, MINT_ADDRESS, MINT_NOISE, TOKEN_DECIMALS, TREASURY,
};
@@ -48,7 +48,7 @@ pub fn process_initialize<'a, 'info>(
let args = InitializeArgs::try_from_bytes(data)?;
// Load accounts
let [signer, bus_0_info, bus_1_info, bus_2_info, bus_3_info, bus_4_info, bus_5_info, bus_6_info, bus_7_info, metadata_info, mint_info, treasury_info, treasury_tokens_info, system_program, token_program, associated_token_program, metadata_program, rent_sysvar] =
let [signer, bus_0_info, bus_1_info, bus_2_info, bus_3_info, bus_4_info, bus_5_info, bus_6_info, bus_7_info, config_info, metadata_info, mint_info, treasury_info, treasury_tokens_info, system_program, token_program, associated_token_program, metadata_program, rent_sysvar] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
@@ -62,6 +62,7 @@ pub fn process_initialize<'a, 'info>(
load_uninitialized_pda(bus_5_info, &[BUS, &[5]], args.bus_5_bump, &crate::id())?;
load_uninitialized_pda(bus_6_info, &[BUS, &[6]], args.bus_6_bump, &crate::id())?;
load_uninitialized_pda(bus_7_info, &[BUS, &[7]], args.bus_7_bump, &crate::id())?;
load_uninitialized_pda(config_info, &[CONFIG], args.config_bump, &crate::id())?;
load_uninitialized_pda(
metadata_info,
&[
@@ -117,6 +118,21 @@ pub fn process_initialize<'a, 'info>(
bus.rewards = 0;
}
// Initialize config
create_pda(
config_info,
&crate::id(),
8 + size_of::<Config>(),
&[CONFIG, &[args.config_bump]],
system_program,
signer,
)?;
let mut config_data = config_info.data.borrow_mut();
config_data[0] = Config::discriminator() as u8;
let config = Config::try_from_bytes_mut(&mut config_data)?;
config.admin = *signer.key;
config.difficulty = INITIAL_DIFFICULTY.into();
// Initialize treasury
create_pda(
treasury_info,
@@ -129,9 +145,7 @@ pub fn process_initialize<'a, 'info>(
let mut treasury_data = treasury_info.data.borrow_mut();
treasury_data[0] = Treasury::discriminator() as u8;
let treasury = Treasury::try_from_bytes_mut(&mut treasury_data)?;
treasury.admin = *signer.key;
treasury.bump = args.treasury_bump as u64;
treasury.difficulty = INITIAL_DIFFICULTY.into();
treasury.last_reset_at = 0;
treasury.reward_rate = INITIAL_REWARD_RATE;
treasury.total_claimed_rewards = 0;

View File

@@ -69,12 +69,16 @@ pub fn process_mine<'a, 'info>(
// Validate provided hash
let mut proof_data = proof_info.data.borrow_mut();
let proof = Proof::try_from_bytes_mut(&mut proof_data)?;
let hash = validate_hash(
proof.hash.into(),
*signer.key,
u64::from_le_bytes(args.nonce),
treasury.difficulty.into(),
)?;
// let hash = validate_hash(
// proof.hash.into(),
// *signer.key,
// u64::from_le_bytes(args.nonce),
// proof.difficulty.into(),
// )?;
// TODO Calculate reward based on difficulty
// TODO Calculate rewards multiplier
// TODO Calculate reward payout amount
// Update claimable rewards
let mut bus_data = bus_info.data.borrow_mut();
@@ -83,11 +87,12 @@ pub fn process_mine<'a, 'info>(
.rewards
.checked_sub(treasury.reward_rate)
.ok_or(OreError::BusRewardsInsufficient)?;
proof.claimable_rewards = proof.claimable_rewards.saturating_add(treasury.reward_rate);
proof.balance = proof.balance.saturating_add(treasury.reward_rate);
// Hash recent slot hash into the next challenge to prevent pre-mining attacks
proof.hash = hashv(&[
hash.as_ref(),
// TODO
// hash.as_ref(),
&slot_hashes_info.data.borrow()[0..size_of::<SlotHash>()],
])
.into();

View File

@@ -4,7 +4,6 @@ mod mine;
mod register;
mod reset;
mod update_admin;
mod update_difficulty;
pub use claim::*;
pub use initialize::*;
@@ -12,4 +11,3 @@ pub use mine::*;
pub use register::*;
pub use reset::*;
pub use update_admin::*;
pub use update_difficulty::*;

View File

@@ -14,6 +14,8 @@ use crate::{
PROOF,
};
// TODO Create a stake account
/// Register generates a new hash chain for a prospective miner. Its responsibilities include:
/// 1. Initialize a new proof account.
/// 2. Generate an initial hash from the signer's key.
@@ -58,12 +60,14 @@ pub fn process_register<'a, 'info>(
proof_data[0] = Proof::discriminator() as u8;
let proof = Proof::try_from_bytes_mut(&mut proof_data)?;
proof.authority = *signer.key;
proof.claimable_rewards = 0;
proof.balance = 0;
proof.hash = hashv(&[
signer.key.as_ref(),
&slot_hashes_info.data.borrow()[0..size_of::<SlotHash>()],
])
.into();
proof.last_hash_at = 0;
proof.multiplier = 1; // TODO
proof.total_hashes = 0;
proof.total_rewards = 0;

View File

@@ -3,7 +3,7 @@ use solana_program::{
pubkey::Pubkey,
};
use crate::{instruction::UpdateAdminArgs, loaders::*, state::Treasury, utils::AccountDeserialize};
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.
@@ -34,21 +34,21 @@ pub fn process_update_admin<'a, 'info>(
let args = UpdateAdminArgs::try_from_bytes(data)?;
// Load accounts
let [signer, treasury_info] = accounts else {
let [signer, config_info] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};
load_signer(signer)?;
load_treasury(treasury_info, true)?;
load_config(config_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) {
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
treasury.admin = args.new_admin;
config.admin = args.new_admin;
Ok(())
}

View File

@@ -1,55 +0,0 @@
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(())
}