entropy_api/state/
var.rs

1use steel::*;
2
3use super::EntropyAccount;
4
5#[repr(C)]
6#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
7pub struct Var {
8    /// The creator of the variable.
9    pub authority: Pubkey,
10
11    /// The id of the variable.
12    pub id: u64,
13
14    /// The provider of the entropy data.
15    pub provider: Pubkey,
16
17    /// The commit provided by Entropy provider.
18    pub commit: [u8; 32],
19
20    /// The revealed seed.
21    pub seed: [u8; 32],
22
23    /// The slot hash
24    pub slot_hash: [u8; 32],
25
26    /// The current value of the variable.
27    pub value: [u8; 32],
28
29    /// The number of random variables remaining to be sampled.
30    pub samples: u64,
31
32    /// Whether or not the Entropy provider should automatically sample the slot hash.
33    pub is_auto: u64,
34
35    /// The slot at which the variable was opened.
36    pub start_at: u64,
37
38    /// The slot at which the variable should sample the slothash.
39    pub end_at: u64,
40}
41
42impl Var {
43    pub fn finalize(&mut self, seed: [u8; 32]) -> ProgramResult {
44        // Silent return.
45        if self.seed != [0; 32] {
46            return Ok(());
47        }
48
49        // Validate the seed.
50        if !self.is_valid(seed) {
51            return Err(trace("Invalid seed", ProgramError::InvalidInstructionData));
52        }
53
54        // Record the revealed seed.
55        self.seed = seed;
56
57        // Finalize the value.
58        self.value = solana_program::keccak::hashv(&[
59            &self.slot_hash,
60            &self.seed,
61            &self.samples.to_le_bytes(),
62        ])
63        .to_bytes();
64
65        Ok(())
66    }
67
68    pub fn is_valid(&self, seed: [u8; 32]) -> bool {
69        if self.slot_hash == [0; 32] {
70            return false;
71        }
72        if self.value != [0; 32] {
73            return false;
74        }
75        if self.samples == 0 {
76            return false;
77        }
78        let expected_commit = solana_program::keccak::hash(&seed).to_bytes();
79        expected_commit == self.commit
80    }
81}
82
83account!(EntropyAccount, Var);