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:
behzad nouri 2022-04-19 13:10:14 +00:00 committed by GitHub
parent 5d1adf1270
commit 16222553b8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 35 additions and 18 deletions

View File

@ -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()];

View File

@ -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
);

View File

@ -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);
}
}