defines const fn for serialized size of VoteState, Feature and Nonce (#24435)
bincode::serialized_sized requires constructing a temporary object and it is slow. Silently changing serialized size of these structs can also be a backward incompatible change. This commit instead hard-codes serialized size of VoteState, Feature and Nonce, and defines the functions as const. Added tests verify hard-coded values.
This commit is contained in:
parent
5d1adf1270
commit
16222553b8
|
@ -1,14 +1,15 @@
|
|||
//! Vote state, vote program
|
||||
//! Receive and processes votes from validators
|
||||
#[cfg(test)]
|
||||
use solana_sdk::epoch_schedule::MAX_LEADER_SCHEDULE_EPOCH_OFFSET;
|
||||
use {
|
||||
crate::{authorized_voters::AuthorizedVoters, id, vote_error::VoteError},
|
||||
bincode::{deserialize, serialize_into, serialized_size, ErrorKind},
|
||||
bincode::{deserialize, serialize_into, ErrorKind},
|
||||
log::*,
|
||||
serde_derive::{Deserialize, Serialize},
|
||||
solana_sdk::{
|
||||
account::{AccountSharedData, ReadableAccount, WritableAccount},
|
||||
clock::{Epoch, Slot, UnixTimestamp},
|
||||
epoch_schedule::MAX_LEADER_SCHEDULE_EPOCH_OFFSET,
|
||||
feature_set::{self, filter_votes_outside_slot_hashes, FeatureSet},
|
||||
hash::Hash,
|
||||
instruction::InstructionError,
|
||||
|
@ -349,11 +350,10 @@ impl VoteState {
|
|||
rent.minimum_balance(VoteState::size_of())
|
||||
}
|
||||
|
||||
pub fn size_of() -> usize {
|
||||
// Upper limit on the size of the Vote State. Equal to
|
||||
// size_of(VoteState) when votes.len() is MAX_LOCKOUT_HISTORY
|
||||
let vote_state = VoteStateVersions::new_current(Self::get_max_sized_vote_state());
|
||||
serialized_size(&vote_state).unwrap() as usize
|
||||
/// Upper limit on the size of the Vote State
|
||||
/// when votes.len() is MAX_LOCKOUT_HISTORY.
|
||||
pub const fn size_of() -> usize {
|
||||
3731 // see test_vote_state_size_of.
|
||||
}
|
||||
|
||||
// utility function, used by Stakes, tests
|
||||
|
@ -416,6 +416,7 @@ impl VoteState {
|
|||
.is_ok()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
fn get_max_sized_vote_state() -> VoteState {
|
||||
let mut authorized_voters = AuthorizedVoters::default();
|
||||
for i in 0..=MAX_LEADER_SCHEDULE_EPOCH_OFFSET {
|
||||
|
@ -2144,6 +2145,14 @@ mod tests {
|
|||
assert_eq!(vote_state.get_authorized_voter(3), Some(new_voter));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vote_state_size_of() {
|
||||
let vote_state = VoteState::get_max_sized_vote_state();
|
||||
let vote_state = VoteStateVersions::new_current(vote_state);
|
||||
let size = bincode::serialized_size(&vote_state).unwrap();
|
||||
assert_eq!(VoteState::size_of() as u64, size);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_vote_state_max_size() {
|
||||
let mut max_sized_data = vec![0; VoteState::size_of()];
|
||||
|
|
|
@ -24,11 +24,8 @@ pub struct Feature {
|
|||
}
|
||||
|
||||
impl Feature {
|
||||
pub fn size_of() -> usize {
|
||||
bincode::serialized_size(&Feature {
|
||||
activated_at: Some(0),
|
||||
})
|
||||
.unwrap() as usize
|
||||
pub const fn size_of() -> usize {
|
||||
9 // see test_feature_size_of.
|
||||
}
|
||||
|
||||
pub fn from_account_info(account_info: &AccountInfo) -> Result<Self, ProgramError> {
|
||||
|
@ -65,7 +62,13 @@ mod test {
|
|||
use {super::*, solana_program::clock::Slot};
|
||||
|
||||
#[test]
|
||||
fn feature_sizeof() {
|
||||
fn test_feature_size_of() {
|
||||
assert_eq!(Feature::size_of() as u64, {
|
||||
let feature = Feature {
|
||||
activated_at: Some(0),
|
||||
};
|
||||
bincode::serialized_size(&feature).unwrap()
|
||||
});
|
||||
assert!(
|
||||
Feature::size_of() >= bincode::serialized_size(&Feature::default()).unwrap() as usize
|
||||
);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use {
|
||||
super::Versions,
|
||||
crate::{fee_calculator::FeeCalculator, hash::Hash, pubkey::Pubkey},
|
||||
serde_derive::{Deserialize, Serialize},
|
||||
};
|
||||
|
@ -60,18 +59,24 @@ impl State {
|
|||
}
|
||||
|
||||
/// Get the serialized size of the nonce state.
|
||||
pub fn size() -> usize {
|
||||
let data = Versions::new_current(State::Initialized(Data::default()));
|
||||
bincode::serialized_size(&data).unwrap() as usize
|
||||
pub const fn size() -> usize {
|
||||
80 // see test_nonce_state_size.
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use {super::*, crate::nonce::state::Versions};
|
||||
|
||||
#[test]
|
||||
fn default_is_uninitialized() {
|
||||
assert_eq!(State::default(), State::Uninitialized)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_nonce_state_size() {
|
||||
let data = Versions::new_current(State::Initialized(Data::default()));
|
||||
let size = bincode::serialized_size(&data).unwrap();
|
||||
assert_eq!(State::size() as u64, size);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue