tape/miner/
register.rs

1use tape_api::prelude::*;
2use solana_program::{
3    keccak::hashv, 
4    slot_hashes::SlotHash
5};
6use steel::*;
7
8pub fn process_register(accounts: &[AccountInfo<'_>], data: &[u8]) -> ProgramResult {
9    let current_time = Clock::get()?.unix_timestamp;
10    let args = Register::try_from_bytes(data)?;
11    let [
12        signer_info,
13        miner_info,
14        archive_info,
15        system_program_info, 
16        rent_info,
17        slot_hashes_info
18    ] = accounts else {
19        return Err(ProgramError::NotEnoughAccountKeys);
20    };
21
22    signer_info.is_signer()?;
23
24    let archive = archive_info
25        .is_archive()?
26        .as_account_mut::<Archive>(&tape_api::ID)?;
27
28    let (miner_pda, _bump) = miner_pda(*signer_info.key, args.name);
29
30    miner_info
31        .is_empty()?
32        .is_writable()?
33        .has_address(&miner_pda)?;
34
35    system_program_info.is_program(&system_program::ID)?;
36    rent_info.is_sysvar(&sysvar::rent::ID)?;
37    slot_hashes_info.is_sysvar(&sysvar::slot_hashes::ID)?;
38
39    // Register miner.
40    create_program_account::<Miner>(
41        miner_info,
42        system_program_info,
43        signer_info,
44        &tape_api::ID,
45        &[MINER, signer_info.key.as_ref(), args.name.as_ref()],
46    )?;
47
48    let miner = miner_info.as_account_mut::<Miner>(&tape_api::ID)?;
49
50    miner.authority         = *signer_info.key;
51    miner.name              = args.name;
52
53    miner.multiplier        = 0;
54    miner.last_proof_hash   = [0; 32];
55    miner.last_proof_at     = current_time;
56    miner.total_proofs      = 0;
57    miner.total_rewards     = 0;
58    miner.unclaimed_rewards = 0;
59
60    let next_challenge = compute_challenge(
61        &miner.current_challenge,
62        slot_hashes_info
63    );
64
65    let recall_tape_number = compute_recall_tape(
66        &next_challenge,
67        archive.tapes_stored
68    );
69
70    miner.current_challenge = next_challenge;
71    miner.recall_tape = recall_tape_number;
72
73    Ok(())
74}
75
76// Helper: compute the next challenge.
77#[inline(always)]
78pub fn compute_challenge(
79    current_challenge: &[u8; 32],
80    slot_hashes_info: &AccountInfo,
81) -> [u8; 32] {
82    let slothash = &slot_hashes_info.data.borrow()
83        [0..core::mem::size_of::<SlotHash>()];
84
85    let next_challenge = hashv(&[
86        current_challenge,
87        slothash,
88    ]).0;
89
90    next_challenge
91}