stake: Add BorshDeserialize trait to structs (#19958)

This commit is contained in:
Jon Cinque 2021-09-17 10:14:23 +02:00 committed by GitHub
parent 40cc243017
commit 9eb98adf97
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 148 additions and 5 deletions

View File

@ -11,6 +11,7 @@ use {
},
stake_history::StakeHistory,
},
borsh::{maybestd::io, BorshDeserialize, BorshSchema},
std::collections::HashSet,
};
@ -23,6 +24,29 @@ pub enum StakeState {
RewardsPool,
}
impl BorshDeserialize for StakeState {
fn deserialize(buf: &mut &[u8]) -> io::Result<Self> {
let enum_value: u32 = BorshDeserialize::deserialize(buf)?;
match enum_value {
0 => Ok(StakeState::Uninitialized),
1 => {
let meta: Meta = BorshDeserialize::deserialize(buf)?;
Ok(StakeState::Initialized(meta))
}
2 => {
let meta: Meta = BorshDeserialize::deserialize(buf)?;
let stake: Stake = BorshDeserialize::deserialize(buf)?;
Ok(StakeState::Stake(meta, stake))
}
3 => Ok(StakeState::RewardsPool),
_ => Err(io::Error::new(
io::ErrorKind::InvalidData,
"Invalid enum value",
)),
}
}
}
impl Default for StakeState {
fn default() -> Self {
StakeState::Uninitialized
@ -75,7 +99,18 @@ pub enum StakeAuthorize {
Withdrawer,
}
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample)]
#[derive(
Default,
Debug,
Serialize,
Deserialize,
PartialEq,
Clone,
Copy,
AbiExample,
BorshDeserialize,
BorshSchema,
)]
pub struct Lockup {
/// UnixTimestamp at which this stake will allow withdrawal, unless the
/// transaction is signed by the custodian
@ -97,7 +132,18 @@ impl Lockup {
}
}
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample)]
#[derive(
Default,
Debug,
Serialize,
Deserialize,
PartialEq,
Clone,
Copy,
AbiExample,
BorshDeserialize,
BorshSchema,
)]
pub struct Authorized {
pub staker: Pubkey,
pub withdrawer: Pubkey,
@ -164,7 +210,18 @@ impl Authorized {
}
}
#[derive(Default, Debug, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample)]
#[derive(
Default,
Debug,
Serialize,
Deserialize,
PartialEq,
Clone,
Copy,
AbiExample,
BorshDeserialize,
BorshSchema,
)]
pub struct Meta {
pub rent_exempt_reserve: u64,
pub authorized: Authorized,
@ -237,7 +294,9 @@ impl Meta {
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample)]
#[derive(
Debug, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample, BorshDeserialize, BorshSchema,
)]
pub struct Delegation {
/// to whom the stake is delegated
pub voter_pubkey: Pubkey,
@ -456,7 +515,18 @@ impl Delegation {
}
}
#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample)]
#[derive(
Debug,
Default,
Serialize,
Deserialize,
PartialEq,
Clone,
Copy,
AbiExample,
BorshDeserialize,
BorshSchema,
)]
pub struct Stake {
pub delegation: Delegation,
/// credits observed is credits from vote account state when delegated or redeemed
@ -496,3 +566,76 @@ impl Stake {
}
}
}
#[cfg(test)]
mod test {
use {
super::*, crate::borsh::try_from_slice_unchecked, assert_matches::assert_matches,
bincode::serialize,
};
fn check_borsh_deserialization(stake: StakeState) {
let serialized = serialize(&stake).unwrap();
let deserialized = StakeState::try_from_slice(&serialized).unwrap();
assert_eq!(stake, deserialized);
}
#[test]
fn bincode_vs_borsh() {
check_borsh_deserialization(StakeState::Uninitialized);
check_borsh_deserialization(StakeState::RewardsPool);
check_borsh_deserialization(StakeState::Initialized(Meta {
rent_exempt_reserve: u64::MAX,
authorized: Authorized {
staker: Pubkey::new_unique(),
withdrawer: Pubkey::new_unique(),
},
lockup: Lockup::default(),
}));
check_borsh_deserialization(StakeState::Stake(
Meta {
rent_exempt_reserve: 1,
authorized: Authorized {
staker: Pubkey::new_unique(),
withdrawer: Pubkey::new_unique(),
},
lockup: Lockup::default(),
},
Stake {
delegation: Delegation {
voter_pubkey: Pubkey::new_unique(),
stake: u64::MAX,
activation_epoch: Epoch::MAX,
deactivation_epoch: Epoch::MAX,
warmup_cooldown_rate: f64::MAX,
},
credits_observed: 1,
},
));
}
#[test]
fn borsh_deserialization_live_data() {
let data = [
1, 0, 0, 0, 128, 213, 34, 0, 0, 0, 0, 0, 133, 0, 79, 231, 141, 29, 73, 61, 232, 35,
119, 124, 168, 12, 120, 216, 195, 29, 12, 166, 139, 28, 36, 182, 186, 154, 246, 149,
224, 109, 52, 100, 133, 0, 79, 231, 141, 29, 73, 61, 232, 35, 119, 124, 168, 12, 120,
216, 195, 29, 12, 166, 139, 28, 36, 182, 186, 154, 246, 149, 224, 109, 52, 100, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
];
// As long as we get the 4-byte enum and the first field right, then
// we're sure the rest works out
let deserialized = try_from_slice_unchecked::<StakeState>(&data).unwrap();
assert_matches!(
deserialized,
StakeState::Initialized(Meta {
rent_exempt_reserve: 2282880,
..
})
);
}
}