1use steel::*;
2
3use super::EntropyAccount;
4
5#[repr(C)]
6#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
7pub struct Var {
8 pub authority: Pubkey,
10
11 pub id: u64,
13
14 pub provider: Pubkey,
16
17 pub commit: [u8; 32],
19
20 pub seed: [u8; 32],
22
23 pub slot_hash: [u8; 32],
25
26 pub value: [u8; 32],
28
29 pub samples: u64,
31
32 pub is_auto: u64,
34
35 pub start_at: u64,
37
38 pub end_at: u64,
40}
41
42impl Var {
43 pub fn finalize(&mut self, seed: [u8; 32]) -> ProgramResult {
44 if self.seed != [0; 32] {
46 return Ok(());
47 }
48
49 if !self.is_valid(seed) {
51 return Err(trace("Invalid seed", ProgramError::InvalidInstructionData));
52 }
53
54 self.seed = seed;
56
57 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);