This commit is contained in:
Hardhat Chad
2024-05-01 13:39:40 +00:00
parent 5d1b1a56aa
commit ac96b5f528
9 changed files with 345 additions and 331 deletions

View File

@@ -1,23 +1,14 @@
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult, program_error::ProgramError,
pubkey::Pubkey, system_program,
account_info::AccountInfo, entrypoint::ProgramResult, program::invoke_signed,
program_error::ProgramError, pubkey::Pubkey, system_program,
};
use crate::{instruction::RegisterArgs, loaders::*};
use crate::{loaders::*, state::Proof, utils::AccountDeserialize, PROOF};
/// 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.
///
/// Safety requirements:
/// - Register is a permissionless instruction and can be invoked by any singer.
/// - Can only succeed if the provided proof acount PDA is valid (associated with the signer).
/// - Can only succeed once per signer.
/// - The provided system program must be valid.
pub fn process_deregister<'a, 'info>(
_program_id: &Pubkey,
accounts: &'a [AccountInfo<'info>],
data: &[u8],
_data: &[u8],
) -> ProgramResult {
// Load accounts
let [signer, proof_info, system_program] = accounts else {
@@ -27,10 +18,37 @@ pub fn process_deregister<'a, 'info>(
load_proof(proof_info, signer.key, true)?;
load_program(system_program, system_program::id())?;
// TODO Ensure proof.balance == 0
// TODO Send lamports to signer
// TODO Realloc data to 0
// TODO Reassign back to system program
// Validate balance is zero
let proof_data = proof_info.data.borrow();
let proof = Proof::try_from_bytes(&proof_data)?;
if proof.balance.gt(&0) {
return Err(ProgramError::InvalidAccountData);
}
// Generate bump
let bump = Pubkey::find_program_address(&[PROOF, signer.key.as_ref()], &crate::id()).1;
// Realloc data to zero
drop(proof_data);
proof_info.realloc(0, false)?;
// Send lamports to signer
invoke_signed(
&solana_program::system_instruction::transfer(
proof_info.key,
signer.key,
proof_info.lamports(),
),
&[proof_info.clone(), signer.clone(), system_program.clone()],
&[&[PROOF, signer.key.as_ref(), &[bump]]],
)?;
// Reassign back to system program
solana_program::program::invoke_signed(
&solana_program::system_instruction::assign(proof_info.key, &system_program::id()),
&[proof_info.clone(), system_program.clone()],
&[&[PROOF, signer.key.as_ref(), &[bump]]],
)?;
Ok(())
}

View File

@@ -179,6 +179,7 @@ pub fn process_initialize<'a, 'info>(
&[&[MINT, MINT_NOISE.as_slice(), &[args.mint_bump]]],
)?;
// TODO Fix metadata initialization
// Initialize mint metadata
// mpl_token_metadata::instructions::CreateMetadataAccountV3Cpi {
// __program: metadata_program,

View File

@@ -14,6 +14,7 @@ use solana_program::{
slot_hashes::SlotHash,
sysvar::{self, instructions::load_current_index, Sysvar},
};
use solana_program::{program::set_return_data, pubkey};
use crate::{
error::OreError,
@@ -21,7 +22,7 @@ use crate::{
loaders::*,
state::{Bus, Config, Proof},
utils::AccountDeserialize,
COMPUTE_BUDGET_PROGRAM_ID, MIN_DIFFICULTY, ONE_MINUTE, TWO_YEARS,
MIN_DIFFICULTY, ONE_MINUTE, TWO_YEARS,
};
/// Mine is the primary workhorse instruction of the Ore program. Its responsibilities include:
@@ -118,23 +119,22 @@ pub fn process_mine<'a, 'info>(
sol_log(&format!("Staking {}", staking_reward));
}
// Apply spam/liveness penalty
// 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_liveness = t_target.saturating_add(config.tolerance_liveness);
if t.lt(&t_spam) {
reward = 0;
sol_log("Spam penalty");
} else if t.gt(&t_liveness) {
}
// Apply liveness penalty
let t_liveness = t_target.saturating_add(config.tolerance_liveness);
if t.gt(&t_liveness) {
reward = reward.saturating_sub(
reward
.saturating_mul(t.saturating_sub(t_liveness) as u64)
.saturating_div(
t_target
.saturating_add(ONE_MINUTE)
.saturating_sub(t_liveness) as u64,
),
.saturating_div(ONE_MINUTE as u64),
);
sol_log(&format!(
"Liveness penalty ({} sec) {}",
@@ -174,7 +174,7 @@ pub fn process_mine<'a, 'info>(
proof.total_rewards = proof.total_rewards.saturating_add(reward);
// Log the mined rewards
// set_return_data(reward.to_le_bytes().as_slice());
set_return_data(reward_actual.to_le_bytes().as_slice());
Ok(())
}
@@ -222,3 +222,6 @@ fn validate_transaction(msg: &[u8]) -> Result<bool, SanitizeError> {
Ok(true)
}
/// Program id of the compute budge program.
const COMPUTE_BUDGET_PROGRAM_ID: Pubkey = pubkey!("ComputeBudget111111111111111111111111111111");

View File

@@ -18,13 +18,12 @@ pub fn process_stake<'a, 'info>(
let amount = u64::from_le_bytes(args.amount);
// Load accounts
let [signer_info, proof_info, sender_info, treasury_tokens_info, token_program] = accounts
else {
let [signer, proof_info, sender_info, treasury_tokens_info, token_program] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};
load_signer(signer_info)?;
load_proof(proof_info, signer_info.key, true)?;
load_token_account(sender_info, Some(signer_info.key), &MINT_ADDRESS, true)?;
load_signer(signer)?;
load_proof(proof_info, signer.key, true)?;
load_token_account(sender_info, Some(signer.key), &MINT_ADDRESS, true)?;
load_token_account(
treasury_tokens_info,
Some(&TREASURY_ADDRESS),
@@ -48,15 +47,15 @@ pub fn process_stake<'a, 'info>(
&spl_token::id(),
sender_info.key,
treasury_tokens_info.key,
signer_info.key,
&[signer_info.key],
signer.key,
&[signer.key],
amount,
)?,
&[
token_program.clone(),
sender_info.clone(),
treasury_tokens_info.clone(),
signer_info.clone(),
signer.clone(),
],
)?;

View File

@@ -4,8 +4,7 @@ use solana_program::{
};
use crate::{
instruction::StakeArgs, loaders::*, state::Treasury, utils::AccountDeserialize, MINT_ADDRESS,
MINT_V1_ADDRESS, TREASURY,
instruction::StakeArgs, loaders::*, MINT_ADDRESS, MINT_V1_ADDRESS, TREASURY, TREASURY_BUMP,
};
pub fn process_upgrade<'a, 'info>(
@@ -18,21 +17,16 @@ pub fn process_upgrade<'a, 'info>(
let amount = u64::from_le_bytes(args.amount);
// Load accounts
let [signer_info, beneficiary_info, mint_info, mint_v1_info, sender_info, treasury_info, token_program] =
let [signer, beneficiary_info, mint_info, mint_v1_info, sender_info, treasury_info, token_program] =
accounts
else {
return Err(ProgramError::NotEnoughAccountKeys);
};
load_signer(signer_info)?;
load_token_account(
beneficiary_info,
Some(&signer_info.key),
&MINT_ADDRESS,
true,
)?;
load_signer(signer)?;
load_token_account(beneficiary_info, Some(&signer.key), &MINT_ADDRESS, true)?;
load_mint(mint_info, MINT_ADDRESS, true)?;
load_mint(mint_v1_info, MINT_V1_ADDRESS, true)?;
load_token_account(sender_info, Some(signer_info.key), &MINT_V1_ADDRESS, true)?;
load_token_account(sender_info, Some(signer.key), &MINT_V1_ADDRESS, true)?;
load_program(token_program, spl_token::id())?;
// Burn v1 tokens
@@ -41,15 +35,15 @@ pub fn process_upgrade<'a, 'info>(
&spl_token::id(),
sender_info.key,
mint_v1_info.key,
signer_info.key,
&[signer_info.key],
signer.key,
&[signer.key],
amount,
)?,
&[
token_program.clone(),
sender_info.clone(),
mint_v1_info.clone(),
signer_info.clone(),
signer.clone(),
],
)?;
@@ -58,10 +52,6 @@ pub fn process_upgrade<'a, 'info>(
let amount_to_mint = amount.saturating_mul(100);
// Mint to the beneficiary account
let treasury_data = treasury_info.data.borrow();
let treasury = Treasury::try_from_bytes(&treasury_data)?;
let treasury_bump = treasury.bump as u8;
drop(treasury_data);
solana_program::program::invoke_signed(
&spl_token::instruction::mint_to(
&spl_token::id(),
@@ -77,7 +67,7 @@ pub fn process_upgrade<'a, 'info>(
beneficiary_info.clone(),
treasury_info.clone(),
],
&[&[TREASURY, &[treasury_bump]]],
&[&[TREASURY, &[TREASURY_BUMP]]],
)?;
Ok(())