From c9ccf96c169df37ec6038be4f088bf3e30dd0df7 Mon Sep 17 00:00:00 2001 From: Hardhat Chad Date: Mon, 29 Jul 2024 00:20:57 +0000 Subject: [PATCH] cleanup --- program/src/auth.rs | 53 --------------------------------------------- program/src/lib.rs | 2 -- program/src/mine.rs | 51 ++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 50 insertions(+), 56 deletions(-) delete mode 100644 program/src/auth.rs diff --git a/program/src/auth.rs b/program/src/auth.rs deleted file mode 100644 index 2489262..0000000 --- a/program/src/auth.rs +++ /dev/null @@ -1,53 +0,0 @@ -use ore_api::consts::COMPUTE_BUDGET_PROGRAM_ID; -use solana_program::{ - pubkey, - pubkey::Pubkey, - sanitize::SanitizeError, - serialize_utils::{read_pubkey, read_u16}, -}; - -/// Get the authenticated pubkey. -/// -/// The intent here is to disincentivize sybil. If a user can fit multiple hashes into a single -/// transaction, there is a financial incentive to sybil multiple keypairs and pack as many hashes -/// as possible into each transaction to minimize fee / hash. -/// -/// If each transaction is limited to one hash only, then a user will minimize their fee / hash -/// by allocating all their hashpower to finding the single most difficult hash they can. -/// -/// We solve this by "authenticating" the proof account on every mine instruction. That is, -/// every transaction with a `mine` instruction needs to include an `auth` instruction that -/// specifies the proof account that will be used. The `auth` instruction must be first ORE -/// instruction in the transaction. The `mine` instruction should error out if the provided proof -/// account doesn't match the authenticated address. -/// -/// Errors if: -/// - Fails to find and parse an authentication address. -pub fn authenticate(data: &[u8]) -> Result, SanitizeError> { - // Start the current byte index at 0 - let mut curr = 0; - let num_instructions = read_u16(&mut curr, data)?; - let pc = curr; - - // Iterate through the transaction instructions - for i in 0..num_instructions as usize { - // Get byte counter - curr = pc + i * 2; - curr = read_u16(&mut curr, data)? as usize; - - // Read the instruction program id - let num_accounts = read_u16(&mut curr, data)? as usize; - curr += num_accounts * 33; - let program_id = read_pubkey(&mut curr, data)?; - - // Introspect on the first non compute budget instruction - if program_id.ne(&COMPUTE_BUDGET_PROGRAM_ID) { - // Read address from ix data - curr += 2; - let address = read_pubkey(&mut curr, data)?; - return Ok(Some(address)); - } - } - - Ok(None) -} diff --git a/program/src/lib.rs b/program/src/lib.rs index 1f51675..bdb31b0 100644 --- a/program/src/lib.rs +++ b/program/src/lib.rs @@ -1,4 +1,3 @@ -mod auth; mod claim; mod close; mod initialize; @@ -9,7 +8,6 @@ mod stake; mod update; mod upgrade; -use auth::*; use claim::*; use close::*; use initialize::*; diff --git a/program/src/mine.rs b/program/src/mine.rs index 0346828..bc8f50a 100644 --- a/program/src/mine.rs +++ b/program/src/mine.rs @@ -18,11 +18,14 @@ use solana_program::{ entrypoint::ProgramResult, log::sol_log, program_error::ProgramError, + pubkey::Pubkey, + sanitize::SanitizeError, + serialize_utils::{read_pubkey, read_u16}, slot_hashes::SlotHash, sysvar::{self, Sysvar}, }; -use crate::{authenticate, utils::AccountDeserialize}; +use crate::utils::AccountDeserialize; /// Mine is the primary workhorse instruction of the Ore program. Its responsibilities include: /// 1. Calculate the hash from the provided nonce. @@ -179,3 +182,49 @@ pub fn process_mine<'a, 'info>(accounts: &'a [AccountInfo<'info>], data: &[u8]) Ok(()) } + +/// Get the authenticated pubkey. +/// +/// The intent here is to disincentivize sybil. If a user can fit multiple hashes into a single +/// transaction, there is a financial incentive to sybil multiple keypairs and pack as many hashes +/// as possible into each transaction to minimize fee / hash. +/// +/// If each transaction is limited to one hash only, then a user will minimize their fee / hash +/// by allocating all their hashpower to finding the single most difficult hash they can. +/// +/// We solve this by "authenticating" the proof account on every mine instruction. That is, +/// every transaction with a `mine` instruction needs to include an `auth` instruction that +/// specifies the proof account that will be used. The `auth` instruction must be first ORE +/// instruction in the transaction. The `mine` instruction should error out if the provided proof +/// account doesn't match the authenticated address. +/// +/// Errors if: +/// - Fails to find and parse an authentication address. +fn authenticate(data: &[u8]) -> Result, SanitizeError> { + // Start the current byte index at 0 + let mut curr = 0; + let num_instructions = read_u16(&mut curr, data)?; + let pc = curr; + + // Iterate through the transaction instructions + for i in 0..num_instructions as usize { + // Get byte counter + curr = pc + i * 2; + curr = read_u16(&mut curr, data)? as usize; + + // Read the instruction program id + let num_accounts = read_u16(&mut curr, data)? as usize; + curr += num_accounts * 33; + let program_id = read_pubkey(&mut curr, data)?; + + // Introspect on the first non compute budget instruction + if program_id.ne(&COMPUTE_BUDGET_PROGRAM_ID) { + // Read address from ix data + curr += 2; + let address = read_pubkey(&mut curr, data)?; + return Ok(Some(address)); + } + } + + Ok(None) +}