1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
#![allow(non_snake_case)]
use crate::cfg_client;
use crate::prelude::*;
use std::cell::Ref;
#[account(zero_copy(unsafe))]
#[repr(packed)]
pub struct VrfLiteAccountData {
/// The bump used to derive the SbState account.
pub state_bump: u8,
/// The bump used to derive the permission account.
pub permission_bump: u8,
/// The VrfPool the account belongs to.
pub vrf_pool: Pubkey,
/// The current status of the VRF account.
pub status: VrfStatus,
/// The VRF round result. Will be zeroized if still awaiting fulfillment.
pub result: [u8; 32],
/// Incremental counter for tracking VRF rounds.
pub counter: u128,
/// The alpha bytes used to calculate the VRF proof.
// TODO: can this be smaller?
pub alpha: [u8; 256],
/// The number of bytes in the alpha buffer.
pub alpha_len: u32,
/// The Slot when the VRF round was opened.
pub request_slot: u64,
/// The unix timestamp when the VRF round was opened.
pub request_timestamp: i64,
/// On-chain account delegated for making account changes.
pub authority: Pubkey,
/// The OracleQueueAccountData that is assigned to fulfill VRF update request.
pub queue: Pubkey,
/// The token account used to hold funds for VRF update request.
pub escrow: Pubkey,
/// The callback that is invoked when an update request is successfully verified.
pub callback: CallbackZC,
/// The incremental VRF proof calculation.
pub builder: VrfBuilder,
// unused currently. may want permission PDA per permission for
// unique expiration periods, BUT currently only one permission
// per account makes sense for the infra. Dont over engineer.
// TODO: should this be epoch or slot ??
pub expiration: i64,
// TODO: Add _ebuf ??
}
impl Default for VrfLiteAccountData {
fn default() -> Self {
unsafe { std::mem::zeroed() }
}
}
impl VrfLiteAccountData {
pub fn size() -> usize {
8 + std::mem::size_of::<VrfLiteAccountData>()
}
/// Returns the deserialized Switchboard VRF Lite account
///
/// # Arguments
///
/// * `switchboard_vrf` - A Solana AccountInfo referencing an existing Switchboard VRF Lite account
///
/// # Examples
///
/// ```ignore
/// use switchboard_solana::VrfLiteAccountData;
///
/// let vrf_lite = VrfLiteAccountData::new(vrf_account_info)?;
/// ```
pub fn new<'info>(
vrf_lite_account_info: &'info AccountInfo,
) -> anchor_lang::Result<Ref<'info, VrfLiteAccountData>> {
let data = vrf_lite_account_info.try_borrow_data()?;
if data.len() < VrfLiteAccountData::discriminator().len() {
return Err(ErrorCode::AccountDiscriminatorNotFound.into());
}
let mut disc_bytes = [0u8; 8];
disc_bytes.copy_from_slice(&data[..8]);
if disc_bytes != VrfLiteAccountData::discriminator() {
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
}
Ok(Ref::map(data, |data| {
bytemuck::from_bytes(&data[8..std::mem::size_of::<VrfLiteAccountData>() + 8])
}))
}
/// Returns the deserialized Switchboard VRF Lite account
///
/// # Arguments
///
/// * `data` - A Solana AccountInfo's data buffer
///
/// # Examples
///
/// ```ignore
/// use switchboard_solana::VrfLiteAccountData;
///
/// let vrf_lite = VrfLiteAccountData::new(vrf_account_info.try_borrow_data()?)?;
/// ```
pub fn new_from_bytes(data: &[u8]) -> anchor_lang::Result<&VrfLiteAccountData> {
if data.len() < VrfLiteAccountData::discriminator().len() {
return Err(ErrorCode::AccountDiscriminatorNotFound.into());
}
let mut disc_bytes = [0u8; 8];
disc_bytes.copy_from_slice(&data[..8]);
if disc_bytes != VrfLiteAccountData::discriminator() {
return Err(ErrorCode::AccountDiscriminatorMismatch.into());
}
Ok(bytemuck::from_bytes(
&data[8..std::mem::size_of::<VrfLiteAccountData>() + 8],
))
}
/// Returns the current VRF round ID
pub fn get_current_randomness_round_id(&self) -> u128 {
self.counter
}
/// If sufficient oracle responses, returns the latest on-chain result in SwitchboardDecimal format
///
/// # Examples
///
/// ```ignore
/// use switchboard_solana::VrfLiteAccountData;
///
/// ```
pub fn get_result(&self) -> anchor_lang::Result<[u8; 32]> {
if self.result == [0u8; 32] {
return Err(error!(SwitchboardError::VrfEmptyError));
}
Ok(self.result)
}
cfg_client! {
pub fn fetch(
client: &solana_client::rpc_client::RpcClient,
pubkey: Pubkey,
) -> std::result::Result<Self, switchboard_common::SbError> {
crate::client::fetch_zerocopy_account(client, pubkey)
}
pub async fn fetch_async(
client: &solana_client::nonblocking::rpc_client::RpcClient,
pubkey: Pubkey,
) -> std::result::Result<Self, switchboard_common::SbError> {
crate::client::fetch_zerocopy_account_async(client, pubkey).await
}
pub fn fetch_sync<T: solana_sdk::client::SyncClient>(
client: &T,
pubkey: Pubkey,
) -> std::result::Result<Self, switchboard_common::SbError> {
crate::client::fetch_zerocopy_account_sync(client, pubkey)
}
}
}