From efe260f12e7a400e8b2dccefff2b4b31575cfe6e Mon Sep 17 00:00:00 2001 From: Rob Walker Date: Mon, 4 Nov 2019 12:31:24 -0800 Subject: [PATCH] sysvar trait (#6667) * sysvar trait * get the new guy in on it --- cli/src/stake.rs | 5 +- ledger/src/staking_utils.rs | 5 +- programs/bpf/rust/sysval/src/lib.rs | 2 +- programs/stake_api/src/stake_instruction.rs | 23 ++++---- .../stake_tests/tests/stake_instruction.rs | 2 +- programs/storage_api/src/storage_processor.rs | 25 ++++----- .../tests/storage_processor.rs | 24 ++++----- programs/vote_api/src/vote_instruction.rs | 12 ++--- runtime/src/bank.rs | 5 +- sdk/src/sysvar/clock.rs | 54 ++++--------------- sdk/src/sysvar/epoch_schedule.rs | 41 ++++---------- sdk/src/sysvar/fees.rs | 38 +++---------- sdk/src/sysvar/mod.rs | 54 ++++++++++++++++++- sdk/src/sysvar/recent_blockhashes.rs | 30 ++++------- sdk/src/sysvar/rent.rs | 38 +++---------- sdk/src/sysvar/rewards.rs | 46 +++------------- sdk/src/sysvar/slot_hashes.rs | 43 ++++----------- sdk/src/sysvar/stake_history.rs | 39 +++++--------- 18 files changed, 183 insertions(+), 303 deletions(-) diff --git a/cli/src/stake.rs b/cli/src/stake.rs index 44b571e60..8b2193554 100644 --- a/cli/src/stake.rs +++ b/cli/src/stake.rs @@ -15,7 +15,10 @@ use solana_sdk::{ pubkey::Pubkey, signature::KeypairUtil, system_instruction::SystemError, - sysvar::stake_history::{self, StakeHistory}, + sysvar::{ + stake_history::{self, StakeHistory}, + Sysvar, + }, transaction::Transaction, }; use solana_stake_api::{ diff --git a/ledger/src/staking_utils.rs b/ledger/src/staking_utils.rs index 6fa6942db..98ef83886 100644 --- a/ledger/src/staking_utils.rs +++ b/ledger/src/staking_utils.rs @@ -105,7 +105,10 @@ pub(crate) mod tests { instruction::Instruction, pubkey::Pubkey, signature::{Keypair, KeypairUtil}, - sysvar::stake_history::{self, StakeHistory}, + sysvar::{ + stake_history::{self, StakeHistory}, + Sysvar, + }, transaction::Transaction, }; use solana_stake_api::{ diff --git a/programs/bpf/rust/sysval/src/lib.rs b/programs/bpf/rust/sysval/src/lib.rs index 8af038f27..0cb2ccc72 100644 --- a/programs/bpf/rust/sysval/src/lib.rs +++ b/programs/bpf/rust/sysval/src/lib.rs @@ -10,7 +10,7 @@ use solana_sdk::{ rent, sysvar::{ clock::Clock, fees::Fees, rent::Rent, rewards::Rewards, slot_hashes::SlotHashes, - stake_history::StakeHistory, + stake_history::StakeHistory, Sysvar, }, }; diff --git a/programs/stake_api/src/stake_instruction.rs b/programs/stake_api/src/stake_instruction.rs index ea27f46f8..30199cbc6 100644 --- a/programs/stake_api/src/stake_instruction.rs +++ b/programs/stake_api/src/stake_instruction.rs @@ -10,7 +10,10 @@ use solana_sdk::{ instruction::{AccountMeta, Instruction, InstructionError}, instruction_processor_utils::{limited_deserialize, next_keyed_account, DecodeError}, pubkey::Pubkey, - system_instruction, sysvar, + system_instruction, + sysvar::{ + self, clock::Clock, rent::Rent, rewards::Rewards, stake_history::StakeHistory, Sysvar, + }, }; /// Reasons the stake might have had an error @@ -330,7 +333,7 @@ pub fn process_instruction( StakeInstruction::Initialize(authorized, lockup) => me.initialize( &authorized, &lockup, - &sysvar::rent::from_keyed_account(next_keyed_account(keyed_accounts)?)?, + &Rent::from_keyed_account(next_keyed_account(keyed_accounts)?)?, ), StakeInstruction::Authorize(authorized_pubkey, stake_authorize) => { me.authorize(&authorized_pubkey, stake_authorize, &signers) @@ -340,7 +343,7 @@ pub fn process_instruction( me.delegate_stake( &vote, - &sysvar::clock::from_keyed_account(next_keyed_account(keyed_accounts)?)?, + &Clock::from_keyed_account(next_keyed_account(keyed_accounts)?)?, &config::from_keyed_account(next_keyed_account(keyed_accounts)?)?, &signers, ) @@ -352,8 +355,8 @@ pub fn process_instruction( me.redeem_vote_credits( vote, rewards_pool, - &sysvar::rewards::from_keyed_account(next_keyed_account(keyed_accounts)?)?, - &sysvar::stake_history::from_keyed_account(next_keyed_account(keyed_accounts)?)?, + &Rewards::from_keyed_account(next_keyed_account(keyed_accounts)?)?, + &StakeHistory::from_keyed_account(next_keyed_account(keyed_accounts)?)?, ) } StakeInstruction::Split(lamports) => { @@ -366,13 +369,13 @@ pub fn process_instruction( me.withdraw( lamports, to, - &sysvar::clock::from_keyed_account(next_keyed_account(keyed_accounts)?)?, - &sysvar::stake_history::from_keyed_account(next_keyed_account(keyed_accounts)?)?, + &Clock::from_keyed_account(next_keyed_account(keyed_accounts)?)?, + &StakeHistory::from_keyed_account(next_keyed_account(keyed_accounts)?)?, &signers, ) } StakeInstruction::Deactivate => me.deactivate_stake( - &sysvar::clock::from_keyed_account(next_keyed_account(keyed_accounts)?)?, + &Clock::from_keyed_account(next_keyed_account(keyed_accounts)?)?, &signers, ), } @@ -390,7 +393,7 @@ mod tests { .iter() .map(|meta| { if sysvar::clock::check_id(&meta.pubkey) { - sysvar::clock::new_account(1, 0, 0, 0, 0) + sysvar::clock::create_account(1, 0, 0, 0, 0) } else if sysvar::rewards::check_id(&meta.pubkey) { sysvar::rewards::create_account(1, 0.0, 0.0) } else if sysvar::stake_history::check_id(&meta.pubkey) { @@ -614,7 +617,7 @@ mod tests { KeyedAccount::new( &sysvar::clock::id(), false, - &mut sysvar::clock::new_account(1, 0, 0, 0, 0) + &mut sysvar::clock::create_account(1, 0, 0, 0, 0) ), KeyedAccount::new( &config::id(), diff --git a/programs/stake_tests/tests/stake_instruction.rs b/programs/stake_tests/tests/stake_instruction.rs index 9abdf38cc..6588fb983 100644 --- a/programs/stake_tests/tests/stake_instruction.rs +++ b/programs/stake_tests/tests/stake_instruction.rs @@ -11,7 +11,7 @@ use solana_sdk::{ message::Message, pubkey::Pubkey, signature::{Keypair, KeypairUtil}, - sysvar::{self, rewards::Rewards}, + sysvar::{self, rewards::Rewards, Sysvar}, }; use solana_stake_api::{ id, diff --git a/programs/storage_api/src/storage_processor.rs b/programs/storage_api/src/storage_processor.rs index 722dbc778..d0e7ed173 100644 --- a/programs/storage_api/src/storage_processor.rs +++ b/programs/storage_api/src/storage_processor.rs @@ -1,13 +1,14 @@ //! storage program //! Receive mining proofs from miners, validate the answers //! and give reward for good proofs. -use crate::storage_contract::StorageAccount; -use crate::storage_instruction::StorageInstruction; -use solana_sdk::account::KeyedAccount; -use solana_sdk::instruction::InstructionError; -use solana_sdk::instruction_processor_utils::limited_deserialize; -use solana_sdk::pubkey::Pubkey; -use solana_sdk::sysvar; +use crate::{storage_contract::StorageAccount, storage_instruction::StorageInstruction}; +use solana_sdk::{ + account::KeyedAccount, + instruction::InstructionError, + instruction_processor_utils::limited_deserialize, + pubkey::Pubkey, + sysvar::{clock::Clock, rewards::Rewards, Sysvar}, +}; pub fn process_instruction( _program_id: &Pubkey, @@ -40,7 +41,7 @@ pub fn process_instruction( // This instruction must be signed by `me` return Err(InstructionError::InvalidArgument); } - let clock = sysvar::clock::from_keyed_account(&rest[0])?; + let clock = Clock::from_keyed_account(&rest[0])?; storage_account.submit_mining_proof( sha_state, segment_index, @@ -54,7 +55,7 @@ pub fn process_instruction( // This instruction must be signed by `me` return Err(InstructionError::InvalidArgument); } - let clock = sysvar::clock::from_keyed_account(&rest[0])?; + let clock = Clock::from_keyed_account(&rest[0])?; storage_account.advertise_storage_recent_blockhash(hash, segment, clock) } StorageInstruction::ClaimStorageReward => { @@ -65,8 +66,8 @@ pub fn process_instruction( let (rewards, rest) = rest.split_at_mut(1); let (rewards_pools, owner) = rest.split_at_mut(1); - let rewards = sysvar::rewards::from_keyed_account(&rewards[0])?; - let clock = sysvar::clock::from_keyed_account(&clock[0])?; + let rewards = Rewards::from_keyed_account(&rewards[0])?; + let clock = Clock::from_keyed_account(&clock[0])?; let mut owner = StorageAccount::new(*owner[0].unsigned_key(), &mut owner[0].account); storage_account.claim_storage_reward(&mut rewards_pools[0], clock, rewards, &mut owner) @@ -82,7 +83,7 @@ pub fn process_instruction( return Err(InstructionError::InvalidArgument); } let me_id = storage_account.id; - let clock = sysvar::clock::from_keyed_account(&clock[0])?; + let clock = Clock::from_keyed_account(&clock[0])?; let mut rest: Vec<_> = rest .iter_mut() .map(|keyed_account| { diff --git a/programs/storage_program/tests/storage_processor.rs b/programs/storage_program/tests/storage_processor.rs index b01035457..06125650f 100644 --- a/programs/storage_program/tests/storage_processor.rs +++ b/programs/storage_program/tests/storage_processor.rs @@ -17,8 +17,11 @@ use solana_sdk::{ pubkey::Pubkey, signature::{Keypair, KeypairUtil, Signature}, system_instruction, - sysvar::clock::{self, Clock}, - sysvar::rewards::{self, Rewards}, + sysvar::{ + clock::{self, Clock}, + rewards::{self, Rewards}, + Sysvar, + }, }; use solana_storage_api::{ id, @@ -131,13 +134,12 @@ fn test_proof_bounds() { Hash::default(), ); // the proof is for segment 0, need to move the slot into segment 2 - let mut clock_account = clock::new_account(1, 0, 0, 0, 0); + let mut clock_account = clock::create_account(1, 0, 0, 0, 0); Clock::to_account( &Clock { slot: DEFAULT_SLOTS_PER_SEGMENT * 2, segment: 2, - epoch: 0, - leader_schedule_epoch: 0, + ..Clock::default() }, &mut clock_account, ); @@ -159,7 +161,7 @@ fn test_serialize_overflow() { let clock_id = clock::id(); let mut keyed_accounts = Vec::new(); let mut user_account = Account::default(); - let mut clock_account = clock::new_account(1, 0, 0, 0, 0); + let mut clock_account = clock::create_account(1, 0, 0, 0, 0); keyed_accounts.push(KeyedAccount::new(&pubkey, true, &mut user_account)); keyed_accounts.push(KeyedAccount::new(&clock_id, false, &mut clock_account)); @@ -184,13 +186,12 @@ fn test_invalid_accounts_len() { Hash::default(), ); // move tick height into segment 1 - let mut clock_account = clock::new_account(1, 0, 0, 0, 0); + let mut clock_account = clock::create_account(1, 0, 0, 0, 0); Clock::to_account( &Clock { slot: 16, segment: 1, - epoch: 0, - leader_schedule_epoch: 0, + ..Clock::default() }, &mut clock_account, ); @@ -244,13 +245,12 @@ fn test_submit_mining_ok() { Hash::default(), ); // move slot into segment 1 - let mut clock_account = clock::new_account(1, 0, 0, 0, 0); + let mut clock_account = clock::create_account(1, 0, 0, 0, 0); Clock::to_account( &Clock { slot: DEFAULT_SLOTS_PER_SEGMENT, segment: 1, - epoch: 0, - leader_schedule_epoch: 0, + ..Clock::default() }, &mut clock_account, ); diff --git a/programs/vote_api/src/vote_instruction.rs b/programs/vote_api/src/vote_instruction.rs index feeab1e1c..7e301ec31 100644 --- a/programs/vote_api/src/vote_instruction.rs +++ b/programs/vote_api/src/vote_instruction.rs @@ -15,7 +15,7 @@ use solana_sdk::{ instruction_processor_utils::{limited_deserialize, DecodeError}, pubkey::Pubkey, system_instruction, - sysvar::{self, rent}, + sysvar::{self, clock::Clock, slot_hashes::SlotHashes, Sysvar}, }; /// Reasons the stake might have had an error @@ -182,7 +182,7 @@ pub fn process_instruction( if rest.is_empty() { return Err(InstructionError::InvalidInstructionData); } - rent::verify_rent_exemption(me, &rest[0])?; + sysvar::rent::verify_rent_exemption(me, &rest[0])?; vote_state::initialize_account(me, &vote_init) } VoteInstruction::Authorize(voter_pubkey, vote_authorize) => { @@ -197,8 +197,8 @@ pub fn process_instruction( vote_state::process_vote( me, - &sysvar::slot_hashes::from_keyed_account(&slot_hashes_and_clock[0])?, - &sysvar::clock::from_keyed_account(&slot_hashes_and_clock[1])?, + &SlotHashes::from_keyed_account(&slot_hashes_and_clock[0])?, + &Clock::from_keyed_account(&slot_hashes_and_clock[1])?, other_signers, &vote, ) @@ -236,11 +236,11 @@ mod tests { .iter() .map(|meta| { if sysvar::clock::check_id(&meta.pubkey) { - sysvar::clock::new_account(1, 0, 0, 0, 0) + sysvar::clock::create_account(1, 0, 0, 0, 0) } else if sysvar::slot_hashes::check_id(&meta.pubkey) { sysvar::slot_hashes::create_account(1, &[]) } else if sysvar::rent::check_id(&meta.pubkey) { - sysvar::rent::create_account(1, &Rent::default()) + Rent::default().create_account(1) } else { Account::default() } diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index e945911e9..b6fc1cef5 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -39,7 +39,8 @@ use solana_sdk::{ pubkey::Pubkey, signature::{Keypair, Signature}, slot_hashes::SlotHashes, - system_transaction, sysvar, + system_transaction, + sysvar::{self, Sysvar}, timing::duration_as_ns, transaction::{Result, Transaction, TransactionError}, }; @@ -447,7 +448,7 @@ impl Bank { fn update_clock(&self) { self.store_account( &sysvar::clock::id(), - &sysvar::clock::new_account( + &sysvar::clock::create_account( 1, self.slot, get_segment_from_slot(self.slot, self.slots_per_segment), diff --git a/sdk/src/sysvar/clock.rs b/sdk/src/sysvar/clock.rs index d4456b5fb..50425b3b1 100644 --- a/sdk/src/sysvar/clock.rs +++ b/sdk/src/sysvar/clock.rs @@ -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 { - 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 { - 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 { - 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()); } diff --git a/sdk/src/sysvar/epoch_schedule.rs b/sdk/src/sysvar/epoch_schedule.rs index ea30e6187..799253acc 100644 --- a/sdk/src/sysvar/epoch_schedule.rs +++ b/sdk/src/sysvar/epoch_schedule.rs @@ -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 { - account.deserialize_data() - } - pub fn from_account(account: &Account) -> Option { - 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 { - 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 { - 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)] diff --git a/sdk/src/sysvar/fees.rs b/sdk/src/sysvar/fees.rs index 531931ed8..386aefac9 100644 --- a/sdk/src/sysvar/fees.rs +++ b/sdk/src/sysvar/fees.rs @@ -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 { - 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 { - 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)] diff --git a/sdk/src/sysvar/mod.rs b/sdk/src/sysvar/mod.rs index 231786d3d..dfabefb14 100644 --- a/sdk/src/sysvar/mod.rs +++ b/sdk/src/sysvar/mod.rs @@ -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 { + 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 { + 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 { + 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 + } +} diff --git a/sdk/src/sysvar/recent_blockhashes.rs b/sdk/src/sysvar/recent_blockhashes.rs index 5df2e6383..24b413e32 100644 --- a/sdk/src/sysvar/recent_blockhashes.rs +++ b/sdk/src/sysvar/recent_blockhashes.rs @@ -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 { - 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 { - 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<()> diff --git a/sdk/src/sysvar/rent.rs b/sdk/src/sysvar/rent.rs index d61895141..403038a8b 100644 --- a/sdk/src/sysvar/rent.rs +++ b/sdk/src/sysvar/rent.rs @@ -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 { - 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 { - 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 { - 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(()) diff --git a/sdk/src/sysvar/rewards.rs b/sdk/src/sysvar/rewards.rs index 468ecc156..4a0fedc5b 100644 --- a/sdk/src/sysvar/rewards.rs +++ b/sdk/src/sysvar/rewards.rs @@ -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 { - 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 { - 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 { - 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)] diff --git a/sdk/src/sysvar/slot_hashes.rs b/sdk/src/sysvar/slot_hashes.rs index 43fd66915..8e41e7163 100644 --- a/sdk/src/sysvar/slot_hashes.rs +++ b/sdk/src/sysvar/slot_hashes.rs @@ -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 { - 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 { - 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 { - 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)] diff --git a/sdk/src/sysvar/stake_history.rs b/sdk/src/sysvar/stake_history.rs index 25370d294..d9d7e7e03 100644 --- a/sdk/src/sysvar/stake_history.rs +++ b/sdk/src/sysvar/stake_history.rs @@ -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 { - 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 { - 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;