agave_transaction_view/
static_account_keys_frame.rs1use {
2 crate::{
3 bytes::{advance_offset_for_array, read_byte},
4 result::{Result, TransactionViewError},
5 },
6 solana_packet::PACKET_DATA_SIZE,
7 solana_pubkey::Pubkey,
8};
9
10pub const MAX_STATIC_ACCOUNTS_PER_PACKET: u8 =
15 (PACKET_DATA_SIZE / core::mem::size_of::<Pubkey>()) as u8;
16
17#[derive(Debug, Default)]
19pub(crate) struct StaticAccountKeysFrame {
20 pub(crate) num_static_accounts: u8,
22 pub(crate) offset: u16,
24}
25
26impl StaticAccountKeysFrame {
27 #[inline(always)]
28 pub(crate) fn try_new(bytes: &[u8], offset: &mut usize) -> Result<Self> {
29 const _: () = assert!(MAX_STATIC_ACCOUNTS_PER_PACKET & 0b1000_0000 == 0);
31
32 let num_static_accounts = read_byte(bytes, offset)?;
33 if num_static_accounts == 0 || num_static_accounts > MAX_STATIC_ACCOUNTS_PER_PACKET {
34 return Err(TransactionViewError::ParseError);
35 }
36
37 let static_accounts_offset = *offset as u16;
41 advance_offset_for_array::<Pubkey>(bytes, offset, u16::from(num_static_accounts))?;
43
44 Ok(Self {
45 num_static_accounts,
46 offset: static_accounts_offset,
47 })
48 }
49}
50
51#[cfg(test)]
52mod tests {
53 use {super::*, solana_short_vec::ShortVec};
54
55 #[test]
56 fn test_zero_accounts() {
57 let bytes = bincode::serialize(&ShortVec(Vec::<Pubkey>::new())).unwrap();
58 let mut offset = 0;
59 assert!(StaticAccountKeysFrame::try_new(&bytes, &mut offset).is_err());
60 }
61
62 #[test]
63 fn test_one_account() {
64 let bytes = bincode::serialize(&ShortVec(vec![Pubkey::default()])).unwrap();
65 let mut offset = 0;
66 let frame = StaticAccountKeysFrame::try_new(&bytes, &mut offset).unwrap();
67 assert_eq!(frame.num_static_accounts, 1);
68 assert_eq!(frame.offset, 1);
69 assert_eq!(offset, 1 + core::mem::size_of::<Pubkey>());
70 }
71
72 #[test]
73 fn test_max_accounts() {
74 let signatures = vec![Pubkey::default(); usize::from(MAX_STATIC_ACCOUNTS_PER_PACKET)];
75 let bytes = bincode::serialize(&ShortVec(signatures)).unwrap();
76 let mut offset = 0;
77 let frame = StaticAccountKeysFrame::try_new(&bytes, &mut offset).unwrap();
78 assert_eq!(frame.num_static_accounts, 38);
79 assert_eq!(frame.offset, 1);
80 assert_eq!(offset, 1 + 38 * core::mem::size_of::<Pubkey>());
81 }
82
83 #[test]
84 fn test_too_many_accounts() {
85 let signatures = vec![Pubkey::default(); usize::from(MAX_STATIC_ACCOUNTS_PER_PACKET) + 1];
86 let bytes = bincode::serialize(&ShortVec(signatures)).unwrap();
87 let mut offset = 0;
88 assert!(StaticAccountKeysFrame::try_new(&bytes, &mut offset).is_err());
89 }
90
91 #[test]
92 fn test_u16_max_accounts() {
93 let signatures = vec![Pubkey::default(); u16::MAX as usize];
94 let bytes = bincode::serialize(&ShortVec(signatures)).unwrap();
95 let mut offset = 0;
96 assert!(StaticAccountKeysFrame::try_new(&bytes, &mut offset).is_err());
97 }
98}