sysvar trait (#6667)

* sysvar trait

* get the new guy in on it
This commit is contained in:
Rob Walker
2019-11-04 12:31:24 -08:00
committed by GitHub
parent b9b535c30f
commit efe260f12e
18 changed files with 183 additions and 303 deletions

View File

@ -4,65 +4,33 @@ pub use crate::clock::Clock;
use crate::{
account::Account,
account_info::AccountInfo,
clock::{Epoch, Segment, Slot},
sysvar,
sysvar::Sysvar,
};
use bincode::serialized_size;
const ID: [u8; 32] = [
6, 167, 213, 23, 24, 199, 116, 201, 40, 86, 99, 152, 105, 29, 94, 182, 139, 94, 184, 163, 155,
75, 109, 92, 115, 85, 91, 33, 0, 0, 0, 0,
];
crate::solana_sysvar_id!(ID, "SysvarC1ock11111111111111111111111111111111");
crate::solana_sysvar_id!(ID, "SysvarC1ock11111111111111111111111111111111", Clock);
impl Clock {
pub fn size_of() -> usize {
serialized_size(&Self::default()).unwrap() as usize
}
pub fn from_account(account: &Account) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account(&self, account: &mut Account) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn from_account_info(account: &AccountInfo) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account_info(&self, account: &mut AccountInfo) -> Option<()> {
account.serialize_data(self).ok()
}
}
impl Sysvar for Clock {}
pub fn new_account(
pub fn create_account(
lamports: u64,
slot: Slot,
segment: Segment,
epoch: Epoch,
leader_schedule_epoch: Epoch,
) -> Account {
Account::new_data(
lamports,
&Clock {
slot,
segment,
epoch,
leader_schedule_epoch,
},
&sysvar::id(),
)
.unwrap()
}
use crate::account::KeyedAccount;
use crate::instruction::InstructionError;
pub fn from_keyed_account(account: &KeyedAccount) -> Result<Clock, InstructionError> {
if !check_id(account.unsigned_key()) {
return Err(InstructionError::InvalidArgument);
Clock {
slot,
segment,
epoch,
leader_schedule_epoch,
}
Clock::from_account(account.account).ok_or(InstructionError::InvalidArgument)
.create_account(lamports)
}
#[cfg(test)]
@ -71,7 +39,7 @@ mod tests {
#[test]
fn test_new() {
let account = new_account(1, 0, 0, 0, 0);
let account = create_account(1, 0, 0, 0, 0);
let clock = Clock::from_account(&account).unwrap();
assert_eq!(clock, Clock::default());
}

View File

@ -1,12 +1,7 @@
//! This account contains the current cluster rent
//!
use crate::{
account::{Account, KeyedAccount},
account_info::AccountInfo,
epoch_schedule::EpochSchedule,
instruction::InstructionError,
sysvar,
};
pub use crate::epoch_schedule::EpochSchedule;
use crate::{account::Account, sysvar::Sysvar};
/// epoch_schedule account pubkey
const ID: [u8; 32] = [
@ -14,34 +9,16 @@ const ID: [u8; 32] = [
30, 63, 80, 135, 25, 168, 5, 0, 0, 0,
];
crate::solana_sysvar_id!(ID, "SysvarEpochSchedu1e111111111111111111111111");
crate::solana_sysvar_id!(
ID,
"SysvarEpochSchedu1e111111111111111111111111",
EpochSchedule
);
impl EpochSchedule {
pub fn deserialize(account: &Account) -> Result<Self, bincode::Error> {
account.deserialize_data()
}
pub fn from_account(account: &Account) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account(&self, account: &mut Account) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn from_account_info(account: &AccountInfo) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account_info(&self, account: &mut AccountInfo) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn from_keyed_account(account: &KeyedAccount) -> Result<EpochSchedule, InstructionError> {
if !check_id(account.unsigned_key()) {
return Err(InstructionError::InvalidArgument);
}
EpochSchedule::from_account(account.account).ok_or(InstructionError::InvalidArgument)
}
}
impl Sysvar for EpochSchedule {}
pub fn create_account(lamports: u64, epoch_schedule: &EpochSchedule) -> Account {
Account::new_data(lamports, epoch_schedule, &sysvar::id()).unwrap()
epoch_schedule.create_account(lamports)
}
#[cfg(test)]

View File

@ -1,10 +1,6 @@
//! This account contains the current cluster fees
//!
use crate::account::Account;
use crate::account_info::AccountInfo;
use crate::fee_calculator::FeeCalculator;
use crate::sysvar;
use bincode::serialized_size;
use crate::{account::Account, fee_calculator::FeeCalculator, sysvar::Sysvar};
/// fees account pubkey
const ID: [u8; 32] = [
@ -12,7 +8,7 @@ const ID: [u8; 32] = [
111, 196, 237, 82, 106, 156, 144, 0, 0, 0, 0,
];
crate::solana_sysvar_id!(ID, "SysvarFees111111111111111111111111111111111");
crate::solana_sysvar_id!(ID, "SysvarFees111111111111111111111111111111111", Fees);
#[repr(C)]
#[derive(Serialize, Deserialize, Debug, Default)]
@ -20,33 +16,13 @@ pub struct Fees {
pub fee_calculator: FeeCalculator,
}
impl Fees {
pub fn from_account(account: &Account) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account(&self, account: &mut Account) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn from_account_info(account: &AccountInfo) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account_info(&self, account: &mut AccountInfo) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn size_of() -> usize {
serialized_size(&Fees::default()).unwrap() as usize
}
}
impl Sysvar for Fees {}
pub fn create_account(lamports: u64, fee_calculator: &FeeCalculator) -> Account {
Account::new_data(
lamports,
&Fees {
fee_calculator: fee_calculator.clone(),
},
&sysvar::id(),
)
.unwrap()
Fees {
fee_calculator: fee_calculator.clone(),
}
.create_account(lamports)
}
#[cfg(test)]

View File

@ -1,6 +1,11 @@
//! named accounts for synthesized data accounts for bank state, etc.
//!
use crate::pubkey::Pubkey;
use crate::{
account::{Account, KeyedAccount},
account_info::AccountInfo,
instruction::InstructionError,
pubkey::Pubkey,
};
pub mod clock;
pub mod epoch_schedule;
@ -24,9 +29,15 @@ pub fn is_sysvar_id(id: &Pubkey) -> bool {
#[macro_export]
macro_rules! solana_sysvar_id(
($id:ident, $name:expr) => (
($id:ident, $name:expr, $type:ty) => (
$crate::solana_name_id!($id, $name);
impl $crate::sysvar::SysvarId for $type {
fn check_id(pubkey: &$crate::pubkey::Pubkey) -> bool {
check_id(pubkey)
}
}
#[cfg(test)]
#[test]
fn test_sysvar_id() {
@ -45,3 +56,42 @@ const ID: [u8; 32] = [
];
crate::solana_name_id!(ID, "Sysvar1111111111111111111111111111111111111");
pub trait SysvarId {
fn check_id(pubkey: &Pubkey) -> bool;
}
// utilities for moving into and out of Accounts
pub trait Sysvar:
SysvarId + Default + Sized + serde::Serialize + serde::de::DeserializeOwned
{
fn biggest() -> Self {
Self::default()
}
fn size_of() -> usize {
bincode::serialized_size(&Self::biggest()).unwrap() as usize
}
fn from_account(account: &Account) -> Option<Self> {
bincode::deserialize(&account.data).ok()
}
fn to_account(&self, account: &mut Account) -> Option<()> {
bincode::serialize_into(&mut account.data[..], self).ok()
}
fn from_account_info(account: &AccountInfo) -> Option<Self> {
bincode::deserialize(&account.data).ok()
}
fn to_account_info(&self, account: &mut AccountInfo) -> Option<()> {
bincode::serialize_into(&mut account.data[..], self).ok()
}
fn from_keyed_account(account: &KeyedAccount) -> Result<Self, InstructionError> {
if !Self::check_id(account.unsigned_key()) {
return Err(InstructionError::InvalidArgument);
}
Self::from_account(account.account).ok_or(InstructionError::InvalidArgument)
}
fn create_account(&self, lamports: u64) -> Account {
let mut account = Account::new(lamports, Self::size_of(), &id());
self.to_account(&mut account).unwrap();
account
}
}

View File

@ -1,5 +1,4 @@
use crate::{account::Account, account_info::AccountInfo, hash::Hash, sysvar};
use bincode::serialized_size;
use crate::{account::Account, hash::Hash, sysvar::Sysvar};
use std::collections::BinaryHeap;
use std::iter::FromIterator;
use std::ops::Deref;
@ -10,7 +9,11 @@ const ID: [u8; 32] = [
0xcf, 0x03, 0x5c, 0x31, 0x45, 0xb2, 0x1a, 0xb3, 0x44, 0xd8, 0x06, 0x2e, 0xa9, 0x40, 0x00, 0x00,
];
crate::solana_sysvar_id!(ID, "SysvarRecentB1ockHashes11111111111111111111");
crate::solana_sysvar_id!(
ID,
"SysvarRecentB1ockHashes11111111111111111111",
RecentBlockhashes
);
#[repr(C)]
#[derive(Serialize, Deserialize, Debug, PartialEq)]
@ -35,22 +38,9 @@ impl<'a> FromIterator<&'a Hash> for RecentBlockhashes {
}
}
impl RecentBlockhashes {
pub fn from_account(account: &Account) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account(&self, account: &mut Account) -> Option<()> {
account.serialize_data(self).unwrap();
Some(())
}
pub fn from_account_info(account: &AccountInfo) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account_info(&self, account: &mut AccountInfo) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn size_of() -> usize {
serialized_size(&RecentBlockhashes(vec![Hash::default(); MAX_ENTRIES])).unwrap() as usize
impl Sysvar for RecentBlockhashes {
fn biggest() -> Self {
RecentBlockhashes(vec![Hash::default(); MAX_ENTRIES])
}
}
@ -62,7 +52,7 @@ impl Deref for RecentBlockhashes {
}
pub fn create_account(lamports: u64) -> Account {
Account::new(lamports, RecentBlockhashes::size_of(), &sysvar::id())
RecentBlockhashes::default().create_account(lamports)
}
pub fn update_account<'a, I>(account: &mut Account, recent_blockhash_iter: I) -> Option<()>

View File

@ -4,11 +4,9 @@ pub use crate::rent::Rent;
use crate::{
account::{Account, KeyedAccount},
account_info::AccountInfo,
instruction::InstructionError,
sysvar,
sysvar::Sysvar,
};
use bincode::serialized_size;
/// rent account pubkey
const ID: [u8; 32] = [
@ -16,44 +14,20 @@ const ID: [u8; 32] = [
253, 68, 227, 219, 217, 138, 0, 0, 0, 0,
];
crate::solana_sysvar_id!(ID, "SysvarRent111111111111111111111111111111111");
crate::solana_sysvar_id!(ID, "SysvarRent111111111111111111111111111111111", Rent);
impl Rent {
pub fn from_account(account: &Account) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account(&self, account: &mut Account) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn from_account_info(account: &AccountInfo) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account_info(&self, account: &mut AccountInfo) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn size_of() -> usize {
serialized_size(&Rent::default()).unwrap() as usize
}
}
impl Sysvar for Rent {}
pub fn create_account(lamports: u64, rent: &Rent) -> Account {
Account::new_data(lamports, rent, &sysvar::id()).unwrap()
}
pub fn from_keyed_account(account: &KeyedAccount) -> Result<Rent, InstructionError> {
if !check_id(account.unsigned_key()) {
return Err(InstructionError::InvalidArgument);
}
Rent::from_account(account.account).ok_or(InstructionError::InvalidArgument)
rent.create_account(lamports)
}
pub fn verify_rent_exemption(
account: &KeyedAccount,
rent_sysvar_account: &KeyedAccount,
) -> Result<(), InstructionError> {
if !from_keyed_account(rent_sysvar_account)?
.is_exempt(account.account.lamports, account.account.data.len())
{
let rent = Rent::from_keyed_account(rent_sysvar_account)?;
if !rent.is_exempt(account.account.lamports, account.account.data.len()) {
Err(InstructionError::InsufficientFunds)
} else {
Ok(())

View File

@ -1,9 +1,6 @@
//! This account contains the current cluster rewards point values
//!
use crate::account::Account;
use crate::account_info::AccountInfo;
use crate::sysvar;
use bincode::serialized_size;
use crate::{account::Account, sysvar::Sysvar};
/// account pubkey
const ID: [u8; 32] = [
@ -11,7 +8,7 @@ const ID: [u8; 32] = [
130, 184, 161, 97, 145, 87, 141, 128, 0, 0, 0,
];
crate::solana_sysvar_id!(ID, "SysvarRewards111111111111111111111111111111");
crate::solana_sysvar_id!(ID, "SysvarRewards111111111111111111111111111111", Rewards);
#[repr(C)]
#[derive(Serialize, Deserialize, Debug, Default, PartialEq)]
@ -20,47 +17,18 @@ pub struct Rewards {
pub storage_point_value: f64,
}
impl Rewards {
pub fn from_account(account: &Account) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account(&self, account: &mut Account) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn from_account_info(account: &AccountInfo) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account_info(&self, account: &mut AccountInfo) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn size_of() -> usize {
serialized_size(&Self::default()).unwrap() as usize
}
}
impl Sysvar for Rewards {}
pub fn create_account(
lamports: u64,
validator_point_value: f64,
storage_point_value: f64,
) -> Account {
Account::new_data(
lamports,
&Rewards {
validator_point_value,
storage_point_value,
},
&sysvar::id(),
)
.unwrap()
}
use crate::account::KeyedAccount;
use crate::instruction::InstructionError;
pub fn from_keyed_account(account: &KeyedAccount) -> Result<Rewards, InstructionError> {
if !check_id(account.unsigned_key()) {
return Err(InstructionError::InvalidArgument);
Rewards {
validator_point_value,
storage_point_value,
}
Rewards::from_account(account.account).ok_or(InstructionError::InvalidAccountData)
.create_account(lamports)
}
#[cfg(test)]

View File

@ -3,51 +3,30 @@
//! this account carries the Bank's most recent blockhashes for some N parents
//!
pub use crate::slot_hashes::{SlotHash, SlotHashes};
use crate::{account::Account, account_info::AccountInfo, sysvar};
use bincode::serialized_size;
use crate::{account::Account, sysvar::Sysvar};
const ID: [u8; 32] = [
6, 167, 213, 23, 25, 47, 10, 175, 198, 242, 101, 227, 251, 119, 204, 122, 218, 130, 197, 41,
208, 190, 59, 19, 110, 45, 0, 85, 32, 0, 0, 0,
];
crate::solana_sysvar_id!(ID, "SysvarS1otHashes111111111111111111111111111");
crate::solana_sysvar_id!(
ID,
"SysvarS1otHashes111111111111111111111111111",
SlotHashes
);
pub const MAX_SLOT_HASHES: usize = 512; // 512 slots to get your vote in
impl SlotHashes {
pub fn from_account(account: &Account) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account(&self, account: &mut Account) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn from_account_info(account: &AccountInfo) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account_info(&self, account: &mut AccountInfo) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn size_of() -> usize {
serialized_size(&SlotHashes::new(&[SlotHash::default(); MAX_SLOT_HASHES])).unwrap() as usize
impl Sysvar for SlotHashes {
fn biggest() -> Self {
// override
SlotHashes::new(&[SlotHash::default(); MAX_SLOT_HASHES])
}
}
pub fn create_account(lamports: u64, slot_hashes: &[SlotHash]) -> Account {
let mut account = Account::new(lamports, SlotHashes::size_of(), &sysvar::id());
SlotHashes::new(slot_hashes)
.to_account(&mut account)
.unwrap();
account
}
use crate::account::KeyedAccount;
use crate::instruction::InstructionError;
pub fn from_keyed_account(account: &KeyedAccount) -> Result<SlotHashes, InstructionError> {
if !check_id(account.unsigned_key()) {
return Err(InstructionError::InvalidArgument);
}
SlotHashes::from_account(account.account).ok_or(InstructionError::InvalidArgument)
SlotHashes::new(slot_hashes).create_account(lamports)
}
#[cfg(test)]

View File

@ -2,10 +2,9 @@
//!
//! this account carries history about stake activations and de-activations
//!
use crate::account_info::AccountInfo;
pub use crate::clock::Epoch;
use crate::{account::Account, sysvar};
use bincode::serialized_size;
use crate::{account::Account, sysvar::Sysvar};
use std::ops::Deref;
const ID: [u8; 32] = [
@ -13,7 +12,11 @@ const ID: [u8; 32] = [
87, 184, 86, 108, 197, 55, 95, 244, 0, 0, 0,
];
crate::solana_sysvar_id!(ID, "SysvarStakeHistory1111111111111111111111111");
crate::solana_sysvar_id!(
ID,
"SysvarStakeHistory1111111111111111111111111",
StakeHistory
);
pub const MAX_STAKE_HISTORY: usize = 512; // it should never take as many as 512 epochs to warm up or cool down
@ -28,27 +31,13 @@ pub struct StakeHistoryEntry {
#[derive(Debug, Serialize, Deserialize, PartialEq, Default, Clone)]
pub struct StakeHistory(Vec<(Epoch, StakeHistoryEntry)>);
impl StakeHistory {
pub fn from_account(account: &Account) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account(&self, account: &mut Account) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn from_account_info(account: &AccountInfo) -> Option<Self> {
account.deserialize_data().ok()
}
pub fn to_account_info(&self, account: &mut AccountInfo) -> Option<()> {
account.serialize_data(self).ok()
}
pub fn size_of() -> usize {
serialized_size(&StakeHistory(vec![
(0, StakeHistoryEntry::default());
MAX_STAKE_HISTORY
]))
.unwrap() as usize
impl Sysvar for StakeHistory {
fn biggest() -> Self {
StakeHistory(vec![(0, StakeHistoryEntry::default()); MAX_STAKE_HISTORY])
}
}
impl StakeHistory {
#[allow(clippy::trivially_copy_pass_by_ref)]
pub fn get(&self, epoch: &Epoch) -> Option<&StakeHistoryEntry> {
self.binary_search_by(|probe| epoch.cmp(&probe.0))
@ -73,9 +62,7 @@ impl Deref for StakeHistory {
}
pub fn create_account(lamports: u64, stake_history: &StakeHistory) -> Account {
let mut account = Account::new(lamports, StakeHistory::size_of(), &sysvar::id());
stake_history.to_account(&mut account).unwrap();
account
stake_history.create_account(lamports)
}
use crate::account::KeyedAccount;