mirror of
https://github.com/d0zingcat/ore.git
synced 2026-05-23 23:16:47 +00:00
groundwork for pick your difficulty
This commit is contained in:
@@ -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)?;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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::*;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
|
||||
@@ -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(())
|
||||
}
|
||||
Reference in New Issue
Block a user