diff --git a/api/src/event.rs b/api/src/event.rs index 80292d6..5eb6b52 100644 --- a/api/src/event.rs +++ b/api/src/event.rs @@ -5,6 +5,7 @@ use crate::state::SwapDirection; pub enum OreEvent { Reset = 0, Swap = 1, + Mine = 2, } #[repr(C)] @@ -81,6 +82,31 @@ pub struct SwapEvent { pub ts: i64, } +#[repr(C)] +#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)] +pub struct MineEvent { + /// The event discriminator. + pub disc: u64, + + /// The authority of the mine. + pub authority: Pubkey, + + /// The block that was mined. + pub block_id: u64, + + /// The nonce that was mined. + pub nonce: u64, + + /// The total hashpower the miner had. + pub hashpower: u64, + + /// Whether or not the miner is the new best. + pub is_best: u64, + + /// The timestamp of the event. + pub ts: i64, +} + impl SwapEvent { pub fn direction(&self) -> SwapDirection { SwapDirection::try_from(self.direction as u8).unwrap() @@ -89,3 +115,4 @@ impl SwapEvent { event!(ResetEvent); event!(SwapEvent); +event!(MineEvent); diff --git a/program/src/mine.rs b/program/src/mine.rs index f79368a..12346aa 100644 --- a/program/src/mine.rs +++ b/program/src/mine.rs @@ -13,7 +13,7 @@ pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult // Load accounts. let clock = Clock::get()?; - let [signer_info, block_info, miner_info] = accounts else { + let [signer_info, block_info, market_info, miner_info, ore_program] = accounts else { return Err(ProgramError::NotEnoughAccountKeys); }; signer_info.is_signer()?; @@ -22,11 +22,13 @@ pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult .assert_mut(|b| clock.slot >= b.end_slot)? // Block has stopped trading .assert_mut(|b| clock.slot < b.end_slot + MINING_WINDOW)? // Give 1500 slots to submit hashes .assert_mut(|b| b.slot_hash != [0; 32])?; // Slot hash is set + market_info.as_account::(&ore_api::ID)?; let miner = miner_info .as_account_mut::(&ore_api::ID)? .assert_mut(|m| m.authority == *signer_info.key)? // Account belongs to authority .assert_mut(|m| m.block_id == block.id)? // Only allow miner to submit hashes for their current block .assert_mut(|m| m.hashpower > nonce)?; // Only allow miner to submit nonces for their hashpower range + ore_program.is_program(&ore_api::ID)?; // Check if the signer is authorized. if !AUTHORIZED_ACCOUNTS.contains(signer_info.key) { @@ -54,6 +56,22 @@ pub fn process_mine(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult block.best_hash_miner = miner.authority; } + // Emit event. + + program_log( + &[market_info.clone(), ore_program.clone()], + &MineEvent { + disc: 2, + authority: *signer_info.key, + block_id: block.id, + nonce, + hashpower: miner.hashpower, + is_best: (block.best_hash_miner == miner.authority) as u64, + ts: clock.unix_timestamp, + } + .to_bytes(), + )?; + // Only allow miners to submit 1 hash per block. miner.hashpower = 0;