switchboard-on-demand 0.5.4

A Rust library to interact with the Switchboard Solana program.
Documentation
#[cfg(feature = "anchor")]
use anchor_lang::solana_program;
use solana_program::account_info::AccountInfo;
use anyhow::Error as AnyhowError;

use crate::sysvar::ed25519_sysvar::{Ed25519Sysvar, ParsedEd25519SignatureDataRef};

#[derive(Copy, Clone, Default, serde::Serialize, serde::Deserialize)]
pub struct Instructions;

#[cfg(feature = "anchor")]
impl anchor_lang::solana_program::sysvar::SysvarId for Instructions {
    fn id() -> solana_program::pubkey::Pubkey {
        solana_program::sysvar::instructions::id().to_bytes().into()
    }

    fn check_id(id: &solana_program::pubkey::Pubkey) -> bool {
        solana_program::sysvar::instructions::id() == id.to_bytes().into()
    }
}
#[cfg(feature = "anchor")]
impl anchor_lang::solana_program::sysvar::Sysvar for Instructions {
    // override
    fn size_of() -> usize {
        // hard-coded so that we don't have to construct an empty
        0 // golden, update if MAX_ENTRIES changes
    }
    fn from_account_info(
        _account_info: &anchor_lang::prelude::AccountInfo,
    ) -> Result<Self, solana_program::program_error::ProgramError> {
        Ok(Self {})
    }
}

impl Instructions {
    pub fn parse_ed25519_from_data(
        data: &[u8],
    ) -> Result<([ParsedEd25519SignatureDataRef<'_>; 8], u8, &[u8], u64, u8), AnyhowError> {
        Ed25519Sysvar::parse_instruction_zero_copy(data).map_err(|e| e)
    }

    #[inline(always)]
    pub fn parse_data(index: usize, data: &[u8]) -> &[u8] {
        use solana_program_ed25519_dalek_bump::serialize_utils::read_u16;
        let mut current = 0;
        assert!(data.len() >= 2);
        let num_instructions = read_u16(&mut current, data).unwrap();
        assert!(index < num_instructions as usize);

        // index into the instruction byte-offset table.
        current += index * 2;
        let start = read_u16(&mut current, data).unwrap();

        current = start as usize;
        current += 34;
        let data_len = read_u16(&mut current, data).unwrap();
        // return slice of the data
        &data[current..current + data_len as usize]
    }

    #[inline(always)]
    pub fn parse_instruction_0_data<'a>(ai: &AccountInfo<'a>) -> &'a [u8] {
        unsafe {
            // Rc<RefCell<&mut [u8]>> -> *mut [u8] -> (*const u8, usize)
            let slice_ptr = (*std::rc::Rc::as_ptr(&ai.data)).as_ptr();
            let base      = (*slice_ptr).as_ptr();

            // --- cursor to ix0 ---
            // p points at start of header
            let mut p = base.add(2);
            let cursor = (p as *const u16).read_unaligned() as usize;

            // p moves to ix0 start
            p = base.add(cursor);

            // accounts_len == 0 (check both bytes, branchless trap)
            let _ = 1u8 / !*p; // trap if non-zero

            // skip accounts_len(2) + program_id(32)
            p = p.add(34);

            // data_len (u16 LE)
            let data_len = (p as *const u16).read_unaligned() as usize;
            p = p.add(2);

            core::slice::from_raw_parts(p, data_len)
        }
    }
}

#[inline(always)]
fn min_branchless(a: u16, b: u16) -> usize {
    // mask = all 1s if a < b, else
    let mask = ((a < b) as i16).wrapping_neg() as u16;
    ((a & mask) | (b & !mask)) as usize
}

// #[inline(always)]
// pub unsafe fn account_data_ptr_len_unchecked(ai: &AccountInfo) -> (*const u8, u16) {
    // let slice_ptr = (*std::rc::Rc::as_ptr(&ai.data)).as_ptr();
    // ((*slice_ptr).as_ptr(), (&(*slice_ptr)).len() as u16)
// }