mirror of
https://github.com/d0zingcat/ore.git
synced 2026-05-13 15:09:57 +00:00
Make boosts mandatory (#121)
* make boosts mandatory * make boosts mandatory * fix account loading * cleanup * cleanup * bump version * nullify reward for invalid boosts
This commit is contained in:
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -1266,7 +1266,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ore-api"
|
||||
version = "3.4.0"
|
||||
version = "3.5.0"
|
||||
dependencies = [
|
||||
"array-const-fn-init",
|
||||
"bytemuck",
|
||||
@@ -1323,11 +1323,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ore-program"
|
||||
version = "3.4.0"
|
||||
version = "3.5.0"
|
||||
dependencies = [
|
||||
"drillx",
|
||||
"mpl-token-metadata",
|
||||
"ore-api 3.4.0",
|
||||
"ore-api 3.5.0",
|
||||
"ore-boost-api 3.0.0",
|
||||
"rand 0.8.5",
|
||||
"solana-program",
|
||||
|
||||
@@ -3,7 +3,7 @@ resolver = "2"
|
||||
members = ["api", "program"]
|
||||
|
||||
[workspace.package]
|
||||
version = "3.4.0"
|
||||
version = "3.5.0"
|
||||
edition = "2021"
|
||||
license = "Apache-2.0"
|
||||
homepage = "https://ore.supply"
|
||||
|
||||
@@ -56,22 +56,21 @@ pub fn mine(
|
||||
authority: Pubkey,
|
||||
bus: Pubkey,
|
||||
solution: Solution,
|
||||
boost_keys: Option<[Pubkey; 2]>,
|
||||
boost: Pubkey,
|
||||
boost_config: Pubkey,
|
||||
) -> Instruction {
|
||||
let proof = proof_pda(authority).0;
|
||||
let mut accounts = vec![
|
||||
let accounts = vec![
|
||||
AccountMeta::new(signer, true),
|
||||
AccountMeta::new(bus, false),
|
||||
AccountMeta::new_readonly(CONFIG_ADDRESS, false),
|
||||
AccountMeta::new(proof, false),
|
||||
AccountMeta::new_readonly(sysvar::instructions::ID, false),
|
||||
AccountMeta::new_readonly(sysvar::slot_hashes::ID, false),
|
||||
AccountMeta::new_readonly(boost, false),
|
||||
AccountMeta::new(proof_pda(boost).0, false),
|
||||
AccountMeta::new_readonly(boost_config, false),
|
||||
];
|
||||
if let Some([boost_address, boost_config_address]) = boost_keys {
|
||||
accounts.push(AccountMeta::new_readonly(boost_address, false));
|
||||
accounts.push(AccountMeta::new(proof_pda(boost_address).0, false));
|
||||
accounts.push(AccountMeta::new_readonly(boost_config_address, false));
|
||||
}
|
||||
Instruction {
|
||||
program_id: crate::ID,
|
||||
accounts,
|
||||
|
||||
@@ -22,7 +22,7 @@ pub fn process_mine(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult {
|
||||
// Load accounts.
|
||||
let clock = Clock::get()?;
|
||||
let t: i64 = clock.unix_timestamp;
|
||||
let (required_accounts, optional_accounts) = accounts.split_at(6);
|
||||
let (required_accounts, boost_accounts) = accounts.split_at(6);
|
||||
let [signer_info, bus_info, config_info, proof_info, instructions_sysvar, slot_hashes_sysvar] =
|
||||
required_accounts
|
||||
else {
|
||||
@@ -34,7 +34,7 @@ pub fn process_mine(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult {
|
||||
.is_config()?
|
||||
.as_account::<Config>(&ore_api::ID)?
|
||||
.assert_err(
|
||||
|c| c.last_reset_at.saturating_add(EPOCH_DURATION) > t,
|
||||
|c| t < c.last_reset_at + EPOCH_DURATION,
|
||||
OreError::NeedsReset.into(),
|
||||
)?;
|
||||
let proof = proof_info
|
||||
@@ -46,6 +46,16 @@ pub fn process_mine(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult {
|
||||
instructions_sysvar.is_sysvar(&sysvar::instructions::ID)?;
|
||||
slot_hashes_sysvar.is_sysvar(&sysvar::slot_hashes::ID)?;
|
||||
|
||||
// Load boost accounts.
|
||||
let [boost_info, boost_proof_info, boost_config_info] = boost_accounts else {
|
||||
return Err(ProgramError::NotEnoughAccountKeys);
|
||||
};
|
||||
let boost = boost_info.as_account::<Boost>(&ore_boost_api::ID)?;
|
||||
let boost_config = boost_config_info.as_account::<BoostConfig>(&ore_boost_api::ID)?;
|
||||
let boost_proof = boost_proof_info
|
||||
.as_account_mut::<Proof>(&ore_api::ID)?
|
||||
.assert_mut(|p| p.authority == *boost_info.key)?;
|
||||
|
||||
// Authenticate the proof account.
|
||||
//
|
||||
// Only one proof account can be used for any given transaction. All `mine` instructions
|
||||
@@ -88,32 +98,27 @@ pub fn process_mine(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult {
|
||||
let normalized_difficulty = difficulty
|
||||
.checked_sub(config.min_difficulty as u32)
|
||||
.unwrap();
|
||||
let base_reward = config
|
||||
let mut base_reward = config
|
||||
.base_reward_rate
|
||||
.checked_mul(2u64.checked_pow(normalized_difficulty).unwrap())
|
||||
.unwrap();
|
||||
|
||||
// Nullify base reward if boost is invalid.
|
||||
if boost_config.current != *boost_info.key || t >= boost_config.ts + ROTATION_DURATION {
|
||||
base_reward = 0;
|
||||
}
|
||||
|
||||
// Apply boosts.
|
||||
//
|
||||
// Boosts are staking incentives that can multiply a miner's rewards. The boost rewards are
|
||||
// split between the miner and staker.
|
||||
let mut boost_reward = 0;
|
||||
if let [boost_info, _boost_proof_info, boost_config_info] = optional_accounts {
|
||||
// Load boost accounts.
|
||||
let boost = boost_info.as_account::<Boost>(&ore_boost_api::ID)?;
|
||||
let boost_config = boost_config_info.as_account::<BoostConfig>(&ore_boost_api::ID)?;
|
||||
|
||||
// Apply multiplier if boost is active, not expired, and last rotation was less than one minute ago
|
||||
if boost_config.current == *boost_info.key
|
||||
&& t < boost_config.ts + ROTATION_DURATION
|
||||
&& t < boost.expires_at
|
||||
{
|
||||
boost_reward = (base_reward as u128)
|
||||
.checked_mul(boost.multiplier as u128)
|
||||
.unwrap()
|
||||
.checked_div(DENOMINATOR_MULTIPLIER as u128)
|
||||
.unwrap() as u64;
|
||||
}
|
||||
if t < boost.expires_at {
|
||||
boost_reward = (base_reward as u128)
|
||||
.checked_mul(boost.multiplier as u128)
|
||||
.unwrap()
|
||||
.checked_div(DENOMINATOR_MULTIPLIER as u128)
|
||||
.unwrap() as u64;
|
||||
}
|
||||
|
||||
// Apply liveness penalty.
|
||||
@@ -198,19 +203,14 @@ pub fn process_mine(accounts: &[AccountInfo], data: &[u8]) -> ProgramResult {
|
||||
|
||||
// Update staker balances.
|
||||
if net_staker_boost_reward > 0 {
|
||||
if let [boost_info, boost_proof_info, _boost_config_info] = optional_accounts {
|
||||
let boost_proof = boost_proof_info
|
||||
.as_account_mut::<Proof>(&ore_api::ID)?
|
||||
.assert_mut(|p| p.authority == *boost_info.key)?;
|
||||
boost_proof.balance = boost_proof
|
||||
.balance
|
||||
.checked_add(net_staker_boost_reward)
|
||||
.unwrap();
|
||||
boost_proof.total_rewards = boost_proof
|
||||
.total_rewards
|
||||
.checked_add(net_staker_boost_reward)
|
||||
.unwrap();
|
||||
}
|
||||
boost_proof.balance = boost_proof
|
||||
.balance
|
||||
.checked_add(net_staker_boost_reward)
|
||||
.unwrap();
|
||||
boost_proof.total_rewards = boost_proof
|
||||
.total_rewards
|
||||
.checked_add(net_staker_boost_reward)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
// Hash a recent slot hash into the next challenge to prevent pre-mining attacks.
|
||||
|
||||
Reference in New Issue
Block a user