mirror of
https://github.com/d0zingcat/ore.git
synced 2026-05-21 15:10:35 +00:00
auth
This commit is contained in:
@@ -23,14 +23,8 @@ pub enum OreError {
|
||||
ToleranceOverflow = 7,
|
||||
#[error("The maximum supply has been reached")]
|
||||
MaxSupply = 8,
|
||||
#[error("This account cannot be closed because it's the top staker")]
|
||||
CannotClose = 9,
|
||||
#[error("This account cannot be crowned because its last stake was too recent")]
|
||||
CannotCrown = 10,
|
||||
#[error("Only the declared proof can be processed in this transaction")]
|
||||
DeclaredProofMissmatch = 11,
|
||||
#[error("Failed to find and parse the declared proof from the transaction")]
|
||||
FindAndParseDeclaredProofFailed = 12,
|
||||
#[error("The proof does not match the expected account")]
|
||||
AuthFailed = 9,
|
||||
}
|
||||
|
||||
impl From<OreError> for ProgramError {
|
||||
|
||||
@@ -17,6 +17,10 @@ use crate::{
|
||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, ShankInstruction, TryFromPrimitive)]
|
||||
#[rustfmt::skip]
|
||||
pub enum OreInstruction {
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "proof", desc = "Ore proof account")]
|
||||
Auth = 0,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
#[account(2, name = "beneficiary", desc = "Beneficiary token account", writable)]
|
||||
@@ -24,13 +28,13 @@ pub enum OreInstruction {
|
||||
#[account(4, name = "treasury", desc = "Ore treasury account", writable)]
|
||||
#[account(5, name = "treasury_tokens", desc = "Ore treasury token account", writable)]
|
||||
#[account(6, name = "token_program", desc = "SPL token program")]
|
||||
Claim = 0,
|
||||
Claim = 1,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
#[account(2, name = "proof", desc = "Ore proof account", writable)]
|
||||
#[account(3, name = "system_program", desc = "Solana system program")]
|
||||
Close = 1,
|
||||
Close = 2,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
@@ -39,7 +43,7 @@ pub enum OreInstruction {
|
||||
#[account(4, name = "noise", desc = "Ore noise account")]
|
||||
#[account(5, name = "proof", desc = "Ore proof account", writable)]
|
||||
#[account(6, name = "slot_hashes", desc = "Solana slot hashes sysvar")]
|
||||
Mine = 2,
|
||||
Mine = 3,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
@@ -48,7 +52,7 @@ pub enum OreInstruction {
|
||||
#[account(4, name = "proof", desc = "Ore proof account", writable)]
|
||||
#[account(5, name = "system_program", desc = "Solana system program")]
|
||||
#[account(6, name = "slot_hashes", desc = "Solana slot hashes sysvar")]
|
||||
Open = 3,
|
||||
Open = 4,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
@@ -65,7 +69,7 @@ pub enum OreInstruction {
|
||||
#[account(12, name = "treasury", desc = "Ore treasury account", writable)]
|
||||
#[account(13, name = "treasury_tokens", desc = "Ore treasury token account", writable)]
|
||||
#[account(14, name = "token_program", desc = "SPL token program")]
|
||||
Reset = 4,
|
||||
Reset = 5,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
@@ -73,12 +77,12 @@ pub enum OreInstruction {
|
||||
#[account(3, name = "sender", desc = "Signer token account", writable)]
|
||||
#[account(4, name = "treasury_tokens", desc = "Ore treasury token account", writable)]
|
||||
#[account(5, name = "token_program", desc = "SPL token program")]
|
||||
Stake = 5,
|
||||
Stake = 6,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
#[account(2, name = "proof", desc = "Ore proof account", writable)]
|
||||
Update = 6,
|
||||
Update = 7,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Signer", signer)]
|
||||
@@ -88,11 +92,7 @@ pub enum OreInstruction {
|
||||
#[account(5, name = "mint", desc = "Ore token mint account", writable)]
|
||||
#[account(6, name = "mint_v1", desc = "Ore v1 token mint account", writable)]
|
||||
#[account(7, name = "token_program", desc = "SPL token program")]
|
||||
Upgrade = 7,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "proof", desc = "Ore proof account")]
|
||||
DeclareProof = 8,
|
||||
Upgrade = 8,
|
||||
|
||||
#[account(0, name = "ore_program", desc = "Ore program")]
|
||||
#[account(1, name = "signer", desc = "Admin signer", signer)]
|
||||
@@ -228,16 +228,12 @@ pub fn close(signer: Pubkey) -> Instruction {
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds a declare proof instruction.
|
||||
pub fn declare_proof(
|
||||
proof: Pubkey,
|
||||
) -> Instruction {
|
||||
/// Builds an auth instruction.
|
||||
pub fn auth(proof: Pubkey) -> Instruction {
|
||||
Instruction {
|
||||
program_id: crate::id(),
|
||||
accounts: vec![
|
||||
AccountMeta::new_readonly(proof, false),
|
||||
],
|
||||
data: OreInstruction::DeclareProof.to_vec(),
|
||||
accounts: vec![AccountMeta::new_readonly(proof, false)],
|
||||
data: OreInstruction::Auth.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
use ore_api::instruction::OreInstruction;
|
||||
use solana_program::{
|
||||
account_info::AccountInfo,
|
||||
entrypoint::ProgramResult,
|
||||
program_error::ProgramError,
|
||||
pubkey,
|
||||
pubkey::Pubkey,
|
||||
sanitize::SanitizeError,
|
||||
serialize_utils::{read_pubkey, read_u16},
|
||||
serialize_utils::{read_pubkey, read_u16, read_u8},
|
||||
};
|
||||
|
||||
|
||||
/// DeclareProof is used by other instructions in the same transaction.
|
||||
/// - Other instructions will use transaction introspection to ensure they
|
||||
/// only process the declared proof.
|
||||
/// - Other instructions will use find_and_parse_declared_proof with the
|
||||
/// - Other instructions will use find_and_parse_declared_proof with the
|
||||
/// introspection data
|
||||
///
|
||||
/// Safety requirements:
|
||||
@@ -19,20 +20,20 @@ use solana_program::{
|
||||
/// low as possible. Other instructions that use the declared proof handle
|
||||
/// validation via the loader.
|
||||
/// - Only one account should be provided.
|
||||
pub fn process_declare_proof<'a, 'info>(
|
||||
pub fn process_auth<'a, 'info>(
|
||||
_program_id: &Pubkey,
|
||||
accounts: &'a [AccountInfo<'info>],
|
||||
_data: &[u8],
|
||||
) -> ProgramResult {
|
||||
let [_proof_info] =
|
||||
accounts
|
||||
else {
|
||||
let [_proof_info] = accounts else {
|
||||
return Err(ProgramError::NotEnoughAccountKeys);
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
const COMPUTE_BUDGET_PROGRAM_ID: Pubkey = pubkey!("ComputeBudget111111111111111111111111111111");
|
||||
|
||||
/// Require that only the declared proof can be processed in this transaction.
|
||||
///
|
||||
/// The intent here is to disincentivize sybil. As long as a user can fit multiple hashes in a single
|
||||
@@ -45,41 +46,38 @@ pub fn process_declare_proof<'a, 'info>(
|
||||
/// Errors if:
|
||||
/// - Fails to find and parse the declared proof pubkey in the second instruction
|
||||
/// of the transaction
|
||||
pub fn find_and_parse_declared_proof(data: &[u8]) -> Result<Pubkey, SanitizeError> {
|
||||
// start the current byte index at 0
|
||||
let mut current = 0;
|
||||
let num_instructions = read_u16(&mut current, data)?;
|
||||
|
||||
if num_instructions < 2 {
|
||||
// Not enough instructions in this transaction.
|
||||
// The declare_proof instruction must be included with
|
||||
// the other instruction in the same transaction.
|
||||
return Err(SanitizeError::IndexOutOfBounds)
|
||||
pub fn authenticate(data: &[u8]) -> Result<Option<Pubkey>, SanitizeError> {
|
||||
// Start the current byte index at 0
|
||||
let mut curr = 0;
|
||||
let num_instructions = read_u16(&mut curr, data)?;
|
||||
let pc = curr;
|
||||
for i in 0..num_instructions as usize {
|
||||
curr = pc + i * 2;
|
||||
curr = read_u16(&mut curr, data)? as usize;
|
||||
let num_accounts = read_u16(&mut curr, data)? as usize;
|
||||
let mut ac = curr;
|
||||
curr += num_accounts * 33;
|
||||
let program_id = read_pubkey(&mut curr, data)?;
|
||||
if program_id.eq(&ore_api::ID) {
|
||||
curr += 2;
|
||||
if let Ok(ix) = OreInstruction::try_from(read_u8(&mut curr, data)?) {
|
||||
// Validate ix is an auth
|
||||
if ix.ne(&OreInstruction::Auth) {
|
||||
return Ok(None);
|
||||
}
|
||||
// Valid num accounts is correct
|
||||
if num_accounts.ne(&1) {
|
||||
return Ok(None);
|
||||
}
|
||||
// Return provided pubkey
|
||||
let address = read_pubkey(&mut ac, data)?;
|
||||
return Ok(Some(address));
|
||||
} else {
|
||||
// Otherwise return
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The first ix should be a set compute budget ix
|
||||
// The second ix should be a declare_proof ix
|
||||
// The starting index is the second ix
|
||||
let index = 1;
|
||||
|
||||
current += index * 2;
|
||||
let start = read_u16(&mut current, data)?;
|
||||
|
||||
current = start as usize;
|
||||
|
||||
current += 2; // skip the accounts length variable
|
||||
current += 1; // skip the meta_byte
|
||||
|
||||
// The only account provided should be the proof pubkey
|
||||
let proof_pubkey = read_pubkey(&mut current, data)?;
|
||||
|
||||
// There shouldn't be any more accounts,
|
||||
// this should be the Ore program ID
|
||||
let program_pubkey = read_pubkey(&mut current, data)?;
|
||||
if program_pubkey.eq(&ore_api::ID) {
|
||||
return Ok(proof_pubkey);
|
||||
} else {
|
||||
return Err(SanitizeError::InvalidValue);
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
mod claim;
|
||||
mod close;
|
||||
mod initialize;
|
||||
mod declare_proof;
|
||||
mod initialize;
|
||||
mod mine;
|
||||
mod open;
|
||||
mod reset;
|
||||
@@ -11,8 +11,8 @@ mod upgrade;
|
||||
|
||||
use claim::*;
|
||||
use close::*;
|
||||
use initialize::*;
|
||||
use declare_proof::*;
|
||||
use initialize::*;
|
||||
use mine::*;
|
||||
use open::*;
|
||||
use reset::*;
|
||||
@@ -45,9 +45,9 @@ pub fn process_instruction(
|
||||
.ok_or(ProgramError::InvalidInstructionData)?;
|
||||
|
||||
match OreInstruction::try_from(*tag).or(Err(ProgramError::InvalidInstructionData))? {
|
||||
OreInstruction::Auth => process_auth(program_id, accounts, data)?,
|
||||
OreInstruction::Claim => process_claim(program_id, accounts, data)?,
|
||||
OreInstruction::Close => process_close(program_id, accounts, data)?,
|
||||
OreInstruction::DeclareProof => process_declare_proof(program_id, accounts, data)?,
|
||||
OreInstruction::Mine => process_mine(program_id, accounts, data)?,
|
||||
OreInstruction::Open => process_open(program_id, accounts, data)?,
|
||||
OreInstruction::Reset => process_reset(program_id, accounts, data)?,
|
||||
|
||||
@@ -5,7 +5,7 @@ use ore_api::{
|
||||
consts::*,
|
||||
error::OreError,
|
||||
event::MineEvent,
|
||||
instruction::{MineArgs, OreInstruction},
|
||||
instruction::MineArgs,
|
||||
loaders::*,
|
||||
state::{Bus, Config, Proof},
|
||||
};
|
||||
@@ -19,13 +19,11 @@ use solana_program::{
|
||||
log::sol_log,
|
||||
program_error::ProgramError,
|
||||
pubkey::Pubkey,
|
||||
sanitize::SanitizeError,
|
||||
serialize_utils::{read_pubkey, read_u16, read_u8},
|
||||
slot_hashes::SlotHash,
|
||||
sysvar::{self, instructions::load_current_index, Sysvar},
|
||||
sysvar::{self, Sysvar},
|
||||
};
|
||||
|
||||
use crate::{find_and_parse_declared_proof, utils::AccountDeserialize};
|
||||
use crate::{authenticate, utils::AccountDeserialize};
|
||||
|
||||
/// Mine is the primary workhorse instruction of the Ore program. Its responsibilities include:
|
||||
/// 1. Calculate the hash from the provided nonce.
|
||||
@@ -62,13 +60,14 @@ pub fn process_mine<'a, 'info>(
|
||||
load_sysvar(instructions_sysvar, sysvar::instructions::id())?;
|
||||
load_sysvar(slot_hashes_sysvar, sysvar::slot_hashes::id())?;
|
||||
|
||||
if let Ok(pubkey) = find_and_parse_declared_proof(&instructions_sysvar.data.borrow()) {
|
||||
if !pubkey.eq(proof_info.key) {
|
||||
return Err(OreError::DeclaredProofMissmatch.into());
|
||||
// Authenticate the proof account
|
||||
if let Ok(Some(auth_address)) = authenticate(&instructions_sysvar.data.borrow()) {
|
||||
if auth_address.ne(proof_info.key) {
|
||||
return Err(OreError::AuthFailed.into());
|
||||
}
|
||||
} else {
|
||||
return Err(OreError::FindAndParseDeclaredProofFailed.into());
|
||||
};
|
||||
return Err(OreError::AuthFailed.into());
|
||||
}
|
||||
|
||||
// Validate epoch is active.
|
||||
let config_data = config_info.data.borrow();
|
||||
@@ -185,4 +184,3 @@ pub fn process_mine<'a, 'info>(
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user