-
-
Save 1500256797/058b40ff351e5b4f96d2e8a7db64b53a to your computer and use it in GitHub Desktop.
Interpreting account data with bytemuck is cheap
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use { | |
bytemuck::{Pod, Zeroable}, | |
pinocchio::{ | |
account_info::AccountInfo, program_entrypoint, | |
pubkey::Pubkey, ProgramResult, program_error::ProgramError, | |
}, | |
}; | |
#[derive(Clone, Copy, Pod, Zeroable)] | |
#[repr(C)] | |
struct SmallData { | |
payload: [Pubkey; 2], | |
} | |
#[derive(Clone, Copy, Pod, Zeroable)] | |
#[repr(C)] | |
struct MediumData { | |
payload: [Pubkey; 16], | |
} | |
#[derive(Clone, Copy, Pod, Zeroable)] | |
#[repr(C)] | |
struct LargeData { | |
payload: [Pubkey; 32], | |
} | |
program_entrypoint!(process_instruction); | |
#[inline(always)] | |
fn process_instruction( | |
_program_id: &Pubkey, | |
accounts: &[AccountInfo], | |
input: &[u8], | |
) -> ProgramResult { | |
let info = &accounts[0]; | |
match input.first() { | |
Some(&0) => { | |
// No-op (base) | |
() | |
} | |
Some(&1) => { | |
// Account data borrow | |
let _ = info.try_borrow_data()?; | |
} | |
Some(&2) => { | |
// bytemuck cast small | |
let data = info.try_borrow_data()?; | |
let _ = bytemuck::from_bytes::<SmallData>(&data); | |
} | |
Some(&3) => { | |
// bytemuck cast medium | |
let data = info.try_borrow_data()?; | |
let _ = bytemuck::from_bytes::<MediumData>(&data); | |
} | |
Some(&4) => { | |
// bytemuck cast large | |
let data = info.try_borrow_data()?; | |
let _ = bytemuck::from_bytes::<LargeData>(&data); | |
} | |
_ => Err(ProgramError::InvalidInstructionData)?, | |
} | |
Ok(()) | |
} | |
#[cfg(all(test, feature = "test-sbf"))] | |
mod tests { | |
use { | |
super::*, | |
mollusk_svm::{result::Check, Mollusk}, | |
solana_account::Account, | |
solana_instruction::{AccountMeta, Instruction}, | |
solana_pubkey::Pubkey, | |
}; | |
fn run_test( | |
ix_dscr: u8, | |
acct_data: &[u8], | |
cus: u64, | |
) { | |
let program_id = Pubkey::new_unique(); | |
let key = Pubkey::new_unique(); | |
Mollusk::new(&program_id, "tests").process_and_validate_instruction( | |
&Instruction::new_with_bytes(program_id, &[ix_dscr], vec![AccountMeta::new(key, false)]), | |
&[(key, Account { data: acct_data.to_vec(), ..Default::default() })], | |
&[Check::success(), Check::compute_units(cus)], | |
); | |
} | |
#[test] | |
fn test_base() { | |
run_test( | |
0, | |
&[], | |
/* CUs: */ 39, | |
); | |
} | |
#[test] | |
fn test_account_borrow() { | |
run_test( | |
1, | |
&[], | |
/* CUs: */ 49, | |
); | |
} | |
#[test] | |
fn test_bytemuck_small() { | |
run_test( | |
2, | |
bytemuck::bytes_of(&SmallData { | |
payload: [[4; 32]; 2], | |
}), | |
/* CUs: */ 55, | |
); | |
} | |
#[test] | |
fn test_bytemuck_medium() { | |
run_test( | |
3, | |
bytemuck::bytes_of(&MediumData { | |
payload: [[4; 32]; 16], | |
}), | |
/* CUs: */ 56, | |
); | |
} | |
#[test] | |
fn test_bytemuck_large() { | |
run_test( | |
4, | |
bytemuck::bytes_of(&LargeData { | |
payload: [[4; 32]; 32], | |
}), | |
/* CUs: */ 56, | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment