Add more sysvar API docs (#26849)

* Add more sysvar API docs

* Remove println from examples

* Update sdk/program/src/clock.rs

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>

* Update sdk/program/src/clock.rs

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>

* Update sdk/program/src/clock.rs

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>

* Update sdk/program/src/clock.rs

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>

* Update sdk/program/src/clock.rs

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>

* Update sdk/program/src/clock.rs

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>

* Update sdk/program/src/clock.rs

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>

* Update sdk/program/src/clock.rs

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>

* Fix docs for ACCOUNT_STORAGE_OVERHEAD

* Update sdk/program/src/epoch_schedule.rs

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>

* Update sdk/program/src/sysvar/slot_hashes.rs

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>

* Update sdk/program/src/sysvar/slot_history.rs

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>

* Update sdk/program/src/sysvar/slot_history.rs

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>

* Update sdk/program/src/sysvar/mod.rs

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>

* Fix docs for DEFAULT_LEADER_SCHEDULE_SLOT_OFFSET

* Fix recent_blockhash short description

* Fix whitespace

Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
This commit is contained in:
Brian Anderson 2022-08-15 13:19:46 -05:00 committed by GitHub
parent 3ad93c84b6
commit b6762fc2f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 889 additions and 186 deletions

View File

@ -44,15 +44,15 @@ fn id_to_tokens(
tokens: &mut proc_macro2::TokenStream,
) {
tokens.extend(quote! {
/// The static program ID
/// The static program ID.
pub static ID: #pubkey_type = #id;
/// Confirms that a given pubkey is equivalent to the program ID
/// Returns `true` if given pubkey is the program ID.
pub fn check_id(id: &#pubkey_type) -> bool {
id == &ID
}
/// Returns the program ID
/// Returns the program ID.
pub fn id() -> #pubkey_type {
ID
}
@ -71,16 +71,16 @@ fn deprecated_id_to_tokens(
tokens: &mut proc_macro2::TokenStream,
) {
tokens.extend(quote! {
/// The static program ID
/// The static program ID.
pub static ID: #pubkey_type = #id;
/// Confirms that a given pubkey is equivalent to the program ID
/// Returns `true` if given pubkey is the program ID.
#[deprecated()]
pub fn check_id(id: &#pubkey_type) -> bool {
id == &ID
}
/// Returns the program ID
/// Returns the program ID.
#[deprecated()]
pub fn id() -> #pubkey_type {
ID

View File

@ -1,20 +1,45 @@
//! Information about the network's clock, ticks, slots, etc.
//!
//! Time in Solana is marked primarily by _slots_, which occur approximately every
//! 400 milliseconds, and are numbered sequentially. For every slot, a leader is
//! chosen from the validator set, and that leader is expected to produce a new
//! block, though sometimes leaders may fail to do so. Blocks can be identified
//! by their slot number, and some slots do not contain a block.
//!
//! An approximation of the passage of real-world time can be calculated by
//! multiplying a number of slots by [`SLOT_MS`], which is a constant target
//! time for the network to produce slots. Note though that this method suffers
//! a variable amount of drift, as the network does not produce slots at exactly
//! the target rate, and the greater number of slots being calculated for, the
//! greater the drift. Epochs cannot be used this way as they contain variable
//! numbers of slots.
//!
//! The network's current view of the real-world time can always be accessed via
//! [`Clock::unix_timestamp`], which is produced by an [oracle derived from the
//! validator set][oracle].
//!
//! [oracle]: https://docs.solana.com/implemented-proposals/validator-timestamp-oracle
use {
crate::{clone_zeroed, copy_field},
std::mem::MaybeUninit,
};
// The default tick rate that the cluster attempts to achieve. Note that the actual tick
// rate at any given time should be expected to drift
/// The default tick rate that the cluster attempts to achieve (160 per second).
///
/// Note that the actual tick rate at any given time should be expected to drift.
pub const DEFAULT_TICKS_PER_SECOND: u64 = 160;
#[cfg(test)]
static_assertions::const_assert_eq!(MS_PER_TICK, 6);
/// The number of milliseconds per tick (6).
pub const MS_PER_TICK: u64 = 1000 / DEFAULT_TICKS_PER_SECOND;
#[cfg(test)]
static_assertions::const_assert_eq!(SLOT_MS, 400);
/// The expected duration of a slot (400 milliseconds).
pub const SLOT_MS: u64 = (DEFAULT_TICKS_PER_SLOT * 1000) / DEFAULT_TICKS_PER_SECOND;
// At 160 ticks/s, 64 ticks per slot implies that leader rotation and voting will happen
@ -41,7 +66,10 @@ pub const TICKS_PER_DAY: u64 = DEFAULT_TICKS_PER_SECOND * SECONDS_PER_DAY;
#[cfg(test)]
static_assertions::const_assert_eq!(DEFAULT_SLOTS_PER_EPOCH, 432_000);
// 1 Epoch ~= 2 days
/// The number of slots per epoch after initial network warmup.
///
/// 1 Epoch ~= 2 days.
pub const DEFAULT_SLOTS_PER_EPOCH: u64 = 2 * TICKS_PER_DAY / DEFAULT_TICKS_PER_SLOT;
// leader schedule is governed by this
@ -52,12 +80,14 @@ static_assertions::const_assert_eq!(DEFAULT_MS_PER_SLOT, 400);
pub const DEFAULT_MS_PER_SLOT: u64 = 1_000 * DEFAULT_TICKS_PER_SLOT / DEFAULT_TICKS_PER_SECOND;
pub const DEFAULT_S_PER_SLOT: f64 = DEFAULT_TICKS_PER_SLOT as f64 / DEFAULT_TICKS_PER_SECOND as f64;
/// The time window of recent block hash values that the bank will track the signatures
/// of over. Once the bank discards a block hash, it will reject any transactions that use
/// that `recent_blockhash` in a transaction. Lowering this value reduces memory consumption,
/// but requires clients to update its `recent_blockhash` more frequently. Raising the value
/// lengthens the time a client must wait to be certain a missing transaction will
/// not be processed by the network.
/// The time window of recent block hash values over which the bank will track
/// signatures.
///
/// Once the bank discards a block hash, it will reject any transactions that
/// use that `recent_blockhash` in a transaction. Lowering this value reduces
/// memory consumption, but requires a client to update its `recent_blockhash`
/// more frequently. Raising the value lengthens the time a client must wait to
/// be certain a missing transaction will not be processed by the network.
pub const MAX_HASH_AGE_IN_SECONDS: usize = 120;
#[cfg(test)]
@ -78,52 +108,61 @@ pub const MAX_TRANSACTION_FORWARDING_DELAY_GPU: usize = 2;
/// More delay is expected if CUDA is not enabled (as signature verification takes longer)
pub const MAX_TRANSACTION_FORWARDING_DELAY: usize = 6;
/// Slot is a unit of time given to a leader for encoding,
/// is some some number of Ticks long.
/// The unit of time given to a leader for encoding a block.
///
/// It is some some number of _ticks_ long.
pub type Slot = u64;
/// Uniquely distinguishes every version of a slot, even if the
/// slot number is the same, i.e. duplicate slots
/// Uniquely distinguishes every version of a slot.
///
/// The `BankId` is unique even if the slot number of two different slots is the
/// same. This can happen in the case of e.g. duplicate slots.
pub type BankId = u64;
/// Epoch is a unit of time a given leader schedule is honored,
/// some number of Slots.
/// The unit of time a given leader schedule is honored.
///
/// It lasts for some number of [`Slot`]s.
pub type Epoch = u64;
pub const GENESIS_EPOCH: Epoch = 0;
// must be sync with Account::rent_epoch::default()
pub const INITIAL_RENT_EPOCH: Epoch = 0;
/// SlotIndex is an index to the slots of a epoch
/// An index to the slots of a epoch.
pub type SlotIndex = u64;
/// SlotCount is the number of slots in a epoch
/// The number of slots in a epoch.
pub type SlotCount = u64;
/// UnixTimestamp is an approximate measure of real-world time,
/// expressed as Unix time (ie. seconds since the Unix epoch)
/// An approximate measure of real-world time.
///
/// Expressed as Unix time (i.e. seconds since the Unix epoch).
pub type UnixTimestamp = i64;
/// Clock represents network time. Members of Clock start from 0 upon
/// network boot. The best way to map Clock to wallclock time is to use
/// current Slot, as Epochs vary in duration (they start short and grow
/// as the network progresses).
/// A representation of network time.
///
/// All members of `Clock` start from 0 upon network boot.
#[repr(C)]
#[derive(Serialize, Deserialize, Debug, Default, PartialEq, Eq)]
pub struct Clock {
/// the current network/bank Slot
/// The current `Slot`.
pub slot: Slot,
/// the timestamp of the first Slot in this Epoch
/// The timestamp of the first `Slot` in this `Epoch`.
pub epoch_start_timestamp: UnixTimestamp,
/// the bank Epoch
/// The current `Epoch`.
pub epoch: Epoch,
/// the future Epoch for which the leader schedule has
/// most recently been calculated
/// The future `Epoch` for which the leader schedule has
/// most recently been calculated.
pub leader_schedule_epoch: Epoch,
/// originally computed from genesis creation time and network time
/// in slots (drifty); corrected using validator timestamp oracle as of
/// timestamp_correction and timestamp_bounding features
/// The approximate real world time of the current slot.
///
/// This value was originally computed from genesis creation time and
/// network time in slots, incurring a lot of drift. Following activation of
/// the [`timestamp_correction` and `timestamp_bounding`][tsc] features it
/// is calculated using a [validator timestamp oracle][oracle].
///
/// [tsc]: https://docs.solana.com/implemented-proposals/bank-timestamp-correction
/// [oracle]: https://docs.solana.com/implemented-proposals/validator-timestamp-oracle
pub unix_timestamp: UnixTimestamp,
}

View File

@ -1,23 +1,34 @@
//! Configuration for epochs and slots.
//!
//! Epochs mark a period of time composed of _slots_, for which a particular
//! [leader schedule][ls] is in effect. The epoch schedule determines the length
//! of epochs, and the timing of the next leader-schedule selection.
//!
//! [ls]: https://docs.solana.com/cluster/leader-rotation#leader-schedule-rotation
//!
//! The epoch schedule does not change during the life of a blockchain,
//! though the length of an epoch does &mdash; during the initial launch of
//! the chain there is a "warmup" period, where epochs are short, with subsequent
//! epochs increasing in slots until they last for [`DEFAULT_SLOTS_PER_EPOCH`].
/// 1 Epoch = 400 * 8192 ms ~= 55 minutes
pub use crate::clock::{Epoch, Slot, DEFAULT_SLOTS_PER_EPOCH};
use {
crate::{clone_zeroed, copy_field},
std::mem::MaybeUninit,
};
/// The number of slots before an epoch starts to calculate the leader schedule.
/// Default is an entire epoch, i.e. leader schedule for epoch X is calculated at
/// the beginning of epoch X - 1.
/// The default number of slots before an epoch starts to calculate the leader schedule.
pub const DEFAULT_LEADER_SCHEDULE_SLOT_OFFSET: u64 = DEFAULT_SLOTS_PER_EPOCH;
/// The maximum number of slots before an epoch starts to calculate the leader schedule.
/// Default is an entire epoch, i.e. leader schedule for epoch X is calculated at
/// the beginning of epoch X - 1.
///
/// Default is an entire epoch, i.e. leader schedule for epoch X is calculated at
/// the beginning of epoch X - 1.
pub const MAX_LEADER_SCHEDULE_EPOCH_OFFSET: u64 = 3;
/// based on MAX_LOCKOUT_HISTORY from vote_program
/// The minimum number of slots per epoch during the warmup period.
///
/// Based on `MAX_LOCKOUT_HISTORY` from `vote_program`.
pub const MINIMUM_SLOTS_PER_EPOCH: u64 = 32;
#[repr(C)]
@ -28,16 +39,20 @@ pub struct EpochSchedule {
pub slots_per_epoch: u64,
/// A number of slots before beginning of an epoch to calculate
/// a leader schedule for that epoch
/// a leader schedule for that epoch.
pub leader_schedule_slot_offset: u64,
/// whether epochs start short and grow
/// Whether epochs start short and grow.
pub warmup: bool,
/// basically: log2(slots_per_epoch) - log2(MINIMUM_SLOTS_PER_EPOCH)
/// The first epoch after the warmup period.
///
/// Basically: `log2(slots_per_epoch) - log2(MINIMUM_SLOTS_PER_EPOCH)`.
pub first_normal_epoch: Epoch,
/// basically: MINIMUM_SLOTS_PER_EPOCH * (2.pow(first_normal_epoch) - 1)
/// The first slot after the warmup period.
///
/// Basically: `MINIMUM_SLOTS_PER_EPOCH * (2.pow(first_normal_epoch) - 1)`.
pub first_normal_slot: Slot,
}

View File

@ -116,6 +116,10 @@ pub mod solana_sdk {
address_lookup_table_account, hash, instruction, keccak, message, nonce,
pubkey::{self, Pubkey},
system_instruction, system_program,
sysvar::{
self,
clock::{self, Clock},
},
};
pub mod account {

View File

@ -28,7 +28,7 @@
//! [serialization]: #serialization
//! [np]: #native-programs
//! [cpi]: #cross-program-instruction-execution
//! [sysvar]: #sysvars
//! [sysvar]: crate::sysvar
//!
//! Idiomatic examples of `solana-program` usage can be found in
//! [the Solana Program Library][spl].
@ -466,89 +466,6 @@
//! - Invokable by programs? yes
//!
//! [lut]: https://docs.solana.com/proposals/transactions-v2
//!
//! # Sysvars
//!
//! Sysvars are special accounts that contain dynamically-updated data about
//! the network cluster, the blockchain history, and the executing transaction.
//!
//! The program IDs for sysvars are defined in the [`sysvar`] module, and simple
//! sysvars implement the [`Sysvar::get`] method, which loads a sysvar directly
//! from the runtime, as in this example that logs the `clock` sysvar:
//!
//! [`Sysvar::get`]: sysvar::Sysvar::get
//!
//! ```
//! use solana_program::{
//! account_info::AccountInfo,
//! clock,
//! entrypoint::ProgramResult,
//! msg,
//! pubkey::Pubkey,
//! sysvar::Sysvar,
//! };
//!
//! fn process_instruction(
//! program_id: &Pubkey,
//! accounts: &[AccountInfo],
//! instruction_data: &[u8],
//! ) -> ProgramResult {
//! let clock = clock::Clock::get()?;
//! msg!("clock: {:#?}", clock);
//! Ok(())
//! }
//! ```
//!
//! Since Solana sysvars are accounts, if the `AccountInfo` is provided to the
//! program, then the program can deserialize the sysvar with
//! [`Sysvar::from_account_info`] to access its data, as in this example that
//! again logs the [`clock`][clk] sysvar.
//!
//! [`Sysvar::from_account_info`]: sysvar::Sysvar::from_account_info
//! [clk]: sysvar::clock
//!
//! ```
//! use solana_program::{
//! account_info::{next_account_info, AccountInfo},
//! clock,
//! entrypoint::ProgramResult,
//! msg,
//! pubkey::Pubkey,
//! sysvar::Sysvar,
//! };
//!
//! fn process_instruction(
//! program_id: &Pubkey,
//! accounts: &[AccountInfo],
//! instruction_data: &[u8],
//! ) -> ProgramResult {
//! let account_info_iter = &mut accounts.iter();
//! let clock_account = next_account_info(account_info_iter)?;
//! let clock = clock::Clock::from_account_info(&clock_account)?;
//! msg!("clock: {:#?}", clock);
//! Ok(())
//! }
//! ```
//!
//! When possible, programs should prefer to call `Sysvar::get` instead of
//! deserializing with `Sysvar::from_account_info`, as the latter imposes extra
//! overhead of deserialization while also requiring the sysvar account address
//! be passed to the program, wasting the limited space available to
//! transactions. Deserializing sysvars that can instead be retrieved with
//! `Sysvar::get` should be only be considered for compatibility with older
//! programs that pass around sysvar accounts.
//!
//! Some sysvars are too large to deserialize within a program, and
//! `Sysvar::from_account_info` returns an error. Some sysvars are too large
//! to deserialize within a program, and attempting to will exhaust the
//! program's compute budget. Some sysvars do not implement `Sysvar::get` and
//! return an error. Some sysvars have custom deserializers that do not
//! implement the `Sysvar` trait. These cases are documented in the modules for
//! individual sysvars.
//!
//! For more details see the Solana [documentation on sysvars][sysvardoc].
//!
//! [sysvardoc]: https://docs.solana.com/developing/runtime-facilities/sysvars
#![allow(incomplete_features)]
#![cfg_attr(RUSTC_WITH_SPECIALIZATION, feature(specialization))]

View File

@ -3,40 +3,53 @@
//! [rent]: https://docs.solana.com/implemented-proposals/rent
#![allow(clippy::integer_arithmetic)]
//! configuration for network rent
use {
crate::{clock::DEFAULT_SLOTS_PER_EPOCH, clone_zeroed, copy_field},
std::mem::MaybeUninit,
};
/// Configuration of network rent.
#[repr(C)]
#[derive(Serialize, Deserialize, PartialEq, Copy, Debug, AbiExample)]
pub struct Rent {
/// Rental rate
/// Rental rate in lamports/byte-year.
pub lamports_per_byte_year: u64,
/// exemption threshold, in years
/// Amount of time (in years) a balance must include rent for the account to
/// be rent exempt.
pub exemption_threshold: f64,
// What portion of collected rent are to be destroyed, percentage-wise
/// The percentage of collected rent that is burned.
///
/// Valid values are in the range [0, 100]. The remaining percentage is
/// distributed to validators.
pub burn_percent: u8,
}
/// default rental rate in lamports/byte-year, based on:
/// 10^9 lamports per SOL
/// $1 per SOL
/// $0.01 per megabyte day
/// $3.65 per megabyte year
/// Default rental rate in lamports/byte-year.
///
/// This calculation is based on:
/// - 10^9 lamports per SOL
/// - $1 per SOL
/// - $0.01 per megabyte day
/// - $3.65 per megabyte year
pub const DEFAULT_LAMPORTS_PER_BYTE_YEAR: u64 = 1_000_000_000 / 100 * 365 / (1024 * 1024);
/// default amount of time (in years) the balance has to include rent for
/// Default amount of time (in years) the balance has to include rent for the
/// account to be rent exempt.
pub const DEFAULT_EXEMPTION_THRESHOLD: f64 = 2.0;
/// default percentage of rent to burn (Valid values are 0 to 100)
/// Default percentage of collected rent that is burned.
///
/// Valid values are in the range [0, 100]. The remaining percentage is
/// distributed to validators.
pub const DEFAULT_BURN_PERCENT: u8 = 50;
/// account storage overhead for calculation of base rent
/// Account storage overhead for calculation of base rent.
///
/// This is the number of bytes required to store an account with no data. It is
/// added to an accounts data length when calculating [`Rent::minimum_balance`].
pub const ACCOUNT_STORAGE_OVERHEAD: u64 = 128;
impl Default for Rent {
@ -63,28 +76,33 @@ impl Clone for Rent {
}
impl Rent {
/// calculate how much rent to burn from the collected rent
/// Calculate how much rent to burn from the collected rent.
///
/// The first value returned is the amount burned. The second is the amount
/// to distribute to validators.
pub fn calculate_burn(&self, rent_collected: u64) -> (u64, u64) {
let burned_portion = (rent_collected * u64::from(self.burn_percent)) / 100;
(burned_portion, rent_collected - burned_portion)
}
/// minimum balance due for rent-exemption of a given size Account::data.len()
/// Minimum balance due for rent-exemption of a given account data size.
///
/// Note: a stripped-down version of this calculation is used in
/// calculate_split_rent_exempt_reserve in the stake program. When this function is updated, --
/// eg. when making rent variable -- the stake program will need to be refactored
/// `calculate_split_rent_exempt_reserve` in the stake program. When this
/// function is updated, eg. when making rent variable, the stake program
/// will need to be refactored.
pub fn minimum_balance(&self, data_len: usize) -> u64 {
let bytes = data_len as u64;
(((ACCOUNT_STORAGE_OVERHEAD + bytes) * self.lamports_per_byte_year) as f64
* self.exemption_threshold) as u64
}
/// whether a given balance and data_len would be exempt
/// Whether a given balance and data length would be exempt.
pub fn is_exempt(&self, balance: u64, data_len: usize) -> bool {
balance >= self.minimum_balance(data_len)
}
/// rent due on account's data_len with balance
/// Rent due on account's data length with balance.
pub fn due(&self, balance: u64, data_len: usize, years_elapsed: f64) -> RentDue {
if self.is_exempt(balance, data_len) {
RentDue::Exempt
@ -93,13 +111,16 @@ impl Rent {
}
}
/// rent due for account that is known to be not exempt
/// Rent due for account that is known to be not exempt.
pub fn due_amount(&self, data_len: usize, years_elapsed: f64) -> u64 {
let actual_data_len = data_len as u64 + ACCOUNT_STORAGE_OVERHEAD;
let lamports_per_year = self.lamports_per_byte_year * actual_data_len;
(lamports_per_year as f64 * years_elapsed) as u64
}
/// Creates a `Rent` that charges no lamports.
///
/// This is used for testing.
pub fn free() -> Self {
Self {
lamports_per_byte_year: 0,
@ -107,6 +128,9 @@ impl Rent {
}
}
/// Creates a `Rent` that is scaled based on the number of slots in an epoch.
///
/// This is used for testing.
pub fn with_slots_per_epoch(slots_per_epoch: u64) -> Self {
let ratio = slots_per_epoch as f64 / DEFAULT_SLOTS_PER_EPOCH as f64;
let exemption_threshold = DEFAULT_EXEMPTION_THRESHOLD as f64 * ratio;
@ -119,17 +143,17 @@ impl Rent {
}
}
/// Enumerate return values from `Rent::due()`
/// The return value of [`Rent::due`].
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum RentDue {
/// Used to indicate the account is rent exempt
/// Used to indicate the account is rent exempt.
Exempt,
/// The account owes rent, and the amount is the field
/// The account owes this much rent.
Paying(u64),
}
impl RentDue {
/// Return the lamports due for rent
/// Return the lamports due for rent.
pub fn lamports(&self) -> u64 {
match self {
RentDue::Exempt => 0,
@ -137,7 +161,7 @@ impl RentDue {
}
}
/// Return 'true' if rent exempt
/// Return 'true' if rent exempt.
pub fn is_exempt(&self) -> bool {
match self {
RentDue::Exempt => true,

View File

@ -4,7 +4,7 @@
//!
//! The sysvar ID is declared in [`sysvar::slot_hashes`].
//!
//! [`sysvar::slot_hashes`]: crate::slot_hashes
//! [`sysvar::slot_hashes`]: crate::sysvar::slot_hashes
pub use crate::clock::Slot;
use {

View File

@ -4,12 +4,13 @@
//!
//! The sysvar ID is declared in [`sysvar::slot_history`].
//!
//! [`sysvar::slot_history`]: crate::slot_history
//! [`sysvar::slot_history`]: crate::sysvar::slot_history
#![allow(clippy::integer_arithmetic)]
pub use crate::clock::Slot;
use bv::{BitVec, BitsMut};
/// A bitvector indicating which slots are present in the past epoch.
#[repr(C)]
#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
pub struct SlotHistory {

View File

@ -1,5 +1,131 @@
//! This account contains the clock slot, epoch, and leader_schedule_epoch
//! Information about the networks clock, ticks, slots, etc.
//!
//! The _clock sysvar_ provides access to the [`Clock`] type, which includes the
//! current slot, the current epoch, and the approximate real-world time of the
//! slot.
//!
//! [`Clock`] implements [`Sysvar::get`] and can be loaded efficiently without
//! passing the sysvar account ID to the program.
//!
//! See also the Solana [documentation on the clock sysvar][sdoc].
//!
//! [sdoc]: https://docs.solana.com/developing/runtime-facilities/sysvars#clock
//!
//! # Examples
//!
//! Accessing via on-chain program directly:
//!
//! ```no_run
//! # use solana_program::{
//! # account_info::{AccountInfo, next_account_info},
//! # entrypoint::ProgramResult,
//! # msg,
//! # pubkey::Pubkey,
//! # sysvar::clock::{self, Clock},
//! # sysvar::Sysvar,
//! # };
//! # use solana_program::program_error::ProgramError;
//! #
//! fn process_instruction(
//! program_id: &Pubkey,
//! accounts: &[AccountInfo],
//! instruction_data: &[u8],
//! ) -> ProgramResult {
//!
//! let clock = Clock::get()?;
//! msg!("clock: {:#?}", clock);
//!
//! Ok(())
//! }
//! #
//! # use solana_program::sysvar::SysvarId;
//! # let p = Clock::id();
//! # let l = &mut 1169280;
//! # let d = &mut vec![240, 153, 233, 7, 0, 0, 0, 0, 11, 115, 118, 98, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 0, 0, 52, 1, 0, 0, 0, 0, 0, 0, 121, 50, 119, 98, 0, 0, 0, 0];
//! # let a = AccountInfo::new(&p, false, false, l, d, &p, false, 0);
//! # let accounts = &[a.clone(), a];
//! # process_instruction(
//! # &Pubkey::new_unique(),
//! # accounts,
//! # &[],
//! # )?;
//! # Ok::<(), ProgramError>(())
//! ```
//!
//! Accessing via on-chain program's account parameters:
//!
//! ```
//! # use solana_program::{
//! # account_info::{AccountInfo, next_account_info},
//! # entrypoint::ProgramResult,
//! # msg,
//! # pubkey::Pubkey,
//! # sysvar::clock::{self, Clock},
//! # sysvar::Sysvar,
//! # };
//! # use solana_program::program_error::ProgramError;
//! #
//! fn process_instruction(
//! program_id: &Pubkey,
//! accounts: &[AccountInfo],
//! instruction_data: &[u8],
//! ) -> ProgramResult {
//! let account_info_iter = &mut accounts.iter();
//! let clock_account_info = next_account_info(account_info_iter)?;
//!
//! assert!(clock::check_id(clock_account_info.key));
//!
//! let clock = Clock::from_account_info(clock_account_info)?;
//! msg!("clock: {:#?}", clock);
//!
//! Ok(())
//! }
//! #
//! # use solana_program::sysvar::SysvarId;
//! # let p = Clock::id();
//! # let l = &mut 1169280;
//! # let d = &mut vec![240, 153, 233, 7, 0, 0, 0, 0, 11, 115, 118, 98, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 0, 0, 52, 1, 0, 0, 0, 0, 0, 0, 121, 50, 119, 98, 0, 0, 0, 0];
//! # let a = AccountInfo::new(&p, false, false, l, d, &p, false, 0);
//! # let accounts = &[a.clone(), a];
//! # process_instruction(
//! # &Pubkey::new_unique(),
//! # accounts,
//! # &[],
//! # )?;
//! # Ok::<(), ProgramError>(())
//! ```
//!
//! Accessing via the RPC client:
//!
//! ```
//! # use solana_program::example_mocks::solana_sdk;
//! # use solana_program::example_mocks::solana_client;
//! # use solana_sdk::account::Account;
//! # use solana_client::rpc_client::RpcClient;
//! # use solana_sdk::sysvar::clock::{self, Clock};
//! # use anyhow::Result;
//! #
//! fn print_sysvar_clock(client: &RpcClient) -> Result<()> {
//! # client.set_get_account_response(clock::ID, Account {
//! # lamports: 1169280,
//! # data: vec![240, 153, 233, 7, 0, 0, 0, 0, 11, 115, 118, 98, 0, 0, 0, 0, 51, 1, 0, 0, 0, 0, 0, 0, 52, 1, 0, 0, 0, 0, 0, 0, 121, 50, 119, 98, 0, 0, 0, 0],
//! # owner: solana_sdk::system_program::ID,
//! # executable: false,
//! # rent_epoch: 307,
//! # });
//! #
//! let clock = client.get_account(&clock::ID)?;
//! let data: Clock = bincode::deserialize(&clock.data)?;
//!
//! Ok(())
//! }
//! #
//! # let client = RpcClient::new(String::new());
//! # print_sysvar_clock(&client)?;
//! #
//! # Ok::<(), anyhow::Error>(())
//! ```
pub use crate::clock::Clock;
use crate::{impl_sysvar_get, program_error::ProgramError, sysvar::Sysvar};

View File

@ -1,5 +1,130 @@
//! This account contains the current cluster rent
//! Information about epoch duration.
//!
//! The _epoch schedule_ sysvar provides access to the [`EpochSchedule`] type,
//! which includes the number of slots per epoch, timing of leader schedule
//! selection, and information about epoch warm-up time.
//!
//! [`EpochSchedule`] implements [`Sysvar::get`] and can be loaded efficiently without
//! passing the sysvar account ID to the program.
//!
//! See also the Solana [documentation on the epoch schedule sysvar][sdoc].
//!
//! [sdoc]: https://docs.solana.com/developing/runtime-facilities/sysvars#epochschedule
//!
//! # Examples
//!
//! Accessing via on-chain program directly:
//!
//! ```no_run
//! # use solana_program::{
//! # account_info::{AccountInfo, next_account_info},
//! # entrypoint::ProgramResult,
//! # msg,
//! # pubkey::Pubkey,
//! # sysvar::epoch_schedule::{self, EpochSchedule},
//! # sysvar::Sysvar,
//! # };
//! # use solana_program::program_error::ProgramError;
//! #
//! fn process_instruction(
//! program_id: &Pubkey,
//! accounts: &[AccountInfo],
//! instruction_data: &[u8],
//! ) -> ProgramResult {
//!
//! let epoch_schedule = EpochSchedule::get()?;
//! msg!("epoch_schedule: {:#?}", epoch_schedule);
//!
//! Ok(())
//! }
//! #
//! # use solana_program::sysvar::SysvarId;
//! # let p = EpochSchedule::id();
//! # let l = &mut 1120560;
//! # let d = &mut vec![0, 32, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
//! # let a = AccountInfo::new(&p, false, false, l, d, &p, false, 0);
//! # let accounts = &[a.clone(), a];
//! # process_instruction(
//! # &Pubkey::new_unique(),
//! # accounts,
//! # &[],
//! # )?;
//! # Ok::<(), ProgramError>(())
//! ```
//!
//! Accessing via on-chain program's account parameters:
//!
//! ```
//! # use solana_program::{
//! # account_info::{AccountInfo, next_account_info},
//! # entrypoint::ProgramResult,
//! # msg,
//! # pubkey::Pubkey,
//! # sysvar::epoch_schedule::{self, EpochSchedule},
//! # sysvar::Sysvar,
//! # };
//! # use solana_program::program_error::ProgramError;
//! #
//! fn process_instruction(
//! program_id: &Pubkey,
//! accounts: &[AccountInfo],
//! instruction_data: &[u8],
//! ) -> ProgramResult {
//! let account_info_iter = &mut accounts.iter();
//! let epoch_schedule_account_info = next_account_info(account_info_iter)?;
//!
//! assert!(epoch_schedule::check_id(epoch_schedule_account_info.key));
//!
//! let epoch_schedule = EpochSchedule::from_account_info(epoch_schedule_account_info)?;
//! msg!("epoch_schedule: {:#?}", epoch_schedule);
//!
//! Ok(())
//! }
//! #
//! # use solana_program::sysvar::SysvarId;
//! # let p = EpochSchedule::id();
//! # let l = &mut 1120560;
//! # let d = &mut vec![0, 32, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
//! # let a = AccountInfo::new(&p, false, false, l, d, &p, false, 0);
//! # let accounts = &[a.clone(), a];
//! # process_instruction(
//! # &Pubkey::new_unique(),
//! # accounts,
//! # &[],
//! # )?;
//! # Ok::<(), ProgramError>(())
//! ```
//!
//! Accessing via the RPC client:
//!
//! ```
//! # use solana_program::example_mocks::solana_sdk;
//! # use solana_program::example_mocks::solana_client;
//! # use solana_sdk::account::Account;
//! # use solana_client::rpc_client::RpcClient;
//! # use solana_sdk::sysvar::epoch_schedule::{self, EpochSchedule};
//! # use anyhow::Result;
//! #
//! fn print_sysvar_epoch_schedule(client: &RpcClient) -> Result<()> {
//! # client.set_get_account_response(epoch_schedule::ID, Account {
//! # lamports: 1120560,
//! # data: vec![0, 32, 0, 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
//! # owner: solana_sdk::system_program::ID,
//! # executable: false,
//! # rent_epoch: 307,
//! # });
//! #
//! let epoch_schedule = client.get_account(&epoch_schedule::ID)?;
//! let data: EpochSchedule = bincode::deserialize(&epoch_schedule.data)?;
//!
//! Ok(())
//! }
//! #
//! # let client = RpcClient::new(String::new());
//! # print_sysvar_epoch_schedule(&client)?;
//! #
//! # Ok::<(), anyhow::Error>(())
//! ```
pub use crate::epoch_schedule::EpochSchedule;
use crate::{impl_sysvar_get, program_error::ProgramError, sysvar::Sysvar};

View File

@ -1,5 +1,23 @@
//! This account contains the current cluster fees
//! Current cluster fees.
//!
//! The _fees sysvar_ provides access to the [`Fees`] type, which contains the
//! current [`FeeCalculator`].
//!
//! [`Fees`] implements [`Sysvar::get`] and can be loaded efficiently without
//! passing the sysvar account ID to the program.
//!
//! This sysvar is deprecated and will not be available in the future.
//! Transaction fees should be determined with the [`getFeeForMessage`] RPC
//! method. For additional context see the [Comprehensive Compute Fees
//! proposal][ccf].
//!
//! [`getFeeForMessage`]: https://docs.solana.com/developing/clients/jsonrpc-api#getfeeformessage
//! [ccf]: https://docs.solana.com/proposals/comprehensive-compute-fees
//!
//! See also the Solana [documentation on the fees sysvar][sdoc].
//!
//! [sdoc]: https://docs.solana.com/developing/runtime-facilities/sysvars#fees
#![allow(deprecated)]
use {
@ -12,6 +30,7 @@ use {
crate::declare_deprecated_sysvar_id!("SysvarFees111111111111111111111111111111111", Fees);
/// Transaction fees.
#[deprecated(
since = "1.9.0",
note = "Please do not use, will no longer be available in the future"

View File

@ -1,5 +1,34 @@
//! The serialized instructions of the current transaction.
//!
//! The _instructions sysvar_ provides access to the serialized instruction data
//! for the currently-running transaction. This allows for [instruction
//! introspection][in], which is required for correctly interoperating with
//! native programs like the [secp256k1] and [ed25519] programs.
//!
//! [in]: https://docs.solana.com/implemented-proposals/instruction_introspection
//! [secp256k1]: crate::secp256k1_program
//! [ed25519]: crate::ed25519_program
//!
//! Unlike other sysvars, the data in the instructions sysvar is not accessed
//! through a type that implements the [`Sysvar`] trait. Instead, the
//! instruction sysvar is accessed through several free functions within this
//! module.
//!
//! [`Sysvar`]: crate::sysvar::Sysvar
//!
//! See also the Solana [documentation on the instructions sysvar][sdoc].
//!
//! [sdoc]: https://docs.solana.com/developing/runtime-facilities/sysvars#instructions
//!
//! # Examples
//!
//! For a complete example of how the instructions sysvar is used see the
//! documentation for [`secp256k1_instruction`] in the `solana-sdk` crate.
//!
//! [`secp256k1_instruction`]: https://docs.rs/solana-sdk/latest/solana_sdk/secp256k1_instruction/index.html
#![allow(clippy::integer_arithmetic)]
//! This account contains the serialized transaction instructions
use crate::{
account_info::AccountInfo,
instruction::{AccountMeta, Instruction},
@ -14,12 +43,23 @@ use {
bitflags::bitflags,
};
// Instructions Sysvar, dummy type, use the associated helpers instead of the Sysvar trait
/// Instructions sysvar, dummy type.
///
/// This type exists for consistency with other sysvar modules, but is a dummy
/// type that does not contain sysvar data. It implements the [`SysvarId`] trait
/// but does not implement the [`Sysvar`] trait.
///
/// [`SysvarId`]: crate::sysvar::SysvarId
/// [`Sysvar`]: crate::sysvar::Sysvar
///
/// Use the free functions in this module to access the instructions sysvar.
pub struct Instructions();
crate::declare_sysvar_id!("Sysvar1nstructions1111111111111111111111111", Instructions);
// Construct the account data for the Instructions Sysvar
/// Construct the account data for the instructions sysvar.
///
/// This function is used by the runtime and not available to Solana programs.
#[cfg(not(target_os = "solana"))]
pub fn construct_instructions_data(instructions: &[BorrowedInstruction]) -> Vec<u8> {
let mut data = serialize_instructions(instructions);
@ -29,14 +69,20 @@ pub fn construct_instructions_data(instructions: &[BorrowedInstruction]) -> Vec<
data
}
/// Borrowed version of AccountMeta
/// Borrowed version of `AccountMeta`.
///
/// This struct is used by the runtime when constructing the sysvar. It is not
/// useful to Solana programs.
pub struct BorrowedAccountMeta<'a> {
pub pubkey: &'a Pubkey,
pub is_signer: bool,
pub is_writable: bool,
}
/// Borrowed version of Instruction
/// Borrowed version of `Instruction`.
///
/// This struct is used by the runtime when constructing the sysvar. It is not
/// useful to Solana programs.
pub struct BorrowedInstruction<'a> {
pub program_id: &'a Pubkey,
pub accounts: Vec<BorrowedAccountMeta<'a>>,
@ -99,7 +145,9 @@ fn serialize_instructions(instructions: &[BorrowedInstruction]) -> Vec<u8> {
}
/// Load the current `Instruction`'s index in the currently executing
/// `Transaction` from the Instructions Sysvar data
/// `Transaction`.
///
/// `data` is the instructions sysvar account data.
#[deprecated(
since = "1.8.0",
note = "Unsafe because the sysvar accounts address is not checked, please use `load_current_index_checked` instead"
@ -112,7 +160,11 @@ pub fn load_current_index(data: &[u8]) -> u16 {
}
/// Load the current `Instruction`'s index in the currently executing
/// `Transaction`
/// `Transaction`.
///
/// # Errors
///
/// Returns [`ProgramError::UnsupportedSysvar`] if the given account's ID is not equal to [`ID`].
pub fn load_current_index_checked(
instruction_sysvar_account_info: &AccountInfo,
) -> Result<u16, ProgramError> {
@ -127,7 +179,7 @@ pub fn load_current_index_checked(
Ok(u16::from_le_bytes(instr_fixed_data))
}
/// Store the current `Instruction`'s index in the Instructions Sysvar data
/// Store the current `Instruction`'s index in the instructions sysvar data.
pub fn store_current_index(data: &mut [u8], instruction_index: u16) {
let last_index = data.len() - 2;
data[last_index..last_index + 2].copy_from_slice(&instruction_index.to_le_bytes());
@ -178,7 +230,9 @@ fn deserialize_instruction(index: usize, data: &[u8]) -> Result<Instruction, San
}
/// Load an `Instruction` in the currently executing `Transaction` at the
/// specified index
/// specified index.
///
/// `data` is the instructions sysvar account data.
#[deprecated(
since = "1.8.0",
note = "Unsafe because the sysvar accounts address is not checked, please use `load_instruction_at_checked` instead"
@ -188,7 +242,11 @@ pub fn load_instruction_at(index: usize, data: &[u8]) -> Result<Instruction, San
}
/// Load an `Instruction` in the currently executing `Transaction` at the
/// specified index
/// specified index.
///
/// # Errors
///
/// Returns [`ProgramError::UnsupportedSysvar`] if the given account's ID is not equal to [`ID`].
pub fn load_instruction_at_checked(
index: usize,
instruction_sysvar_account_info: &AccountInfo,
@ -205,7 +263,11 @@ pub fn load_instruction_at_checked(
}
/// Returns the `Instruction` relative to the current `Instruction` in the
/// currently executing `Transaction`
/// currently executing `Transaction`.
///
/// # Errors
///
/// Returns [`ProgramError::UnsupportedSysvar`] if the given account's ID is not equal to [`ID`].
pub fn get_instruction_relative(
index_relative_to_current: i64,
instruction_sysvar_account_info: &AccountInfo,

View File

@ -1,5 +1,82 @@
//! Access to special accounts with dynamically-updated data.
//!
//! Sysvars are special accounts that contain dynamically-updated data about the
//! network cluster, the blockchain history, and the executing transaction. Each
//! sysvar is defined in its own submodule within this module. The [`clock`],
//! [`epoch_schedule`], [`instructions`], and [`rent`] sysvars are most useful
//! to on-chain programs.
//!
//! Simple sysvars implement the [`Sysvar::get`] method, which loads a sysvar
//! directly from the runtime, as in this example that logs the `clock` sysvar:
//!
//! ```
//! use solana_program::{
//! account_info::AccountInfo,
//! clock,
//! entrypoint::ProgramResult,
//! msg,
//! pubkey::Pubkey,
//! sysvar::Sysvar,
//! };
//!
//! fn process_instruction(
//! program_id: &Pubkey,
//! accounts: &[AccountInfo],
//! instruction_data: &[u8],
//! ) -> ProgramResult {
//! let clock = clock::Clock::get()?;
//! msg!("clock: {:#?}", clock);
//! Ok(())
//! }
//! ```
//!
//! Since Solana sysvars are accounts, if the `AccountInfo` is provided to the
//! program, then the program can deserialize the sysvar with
//! [`Sysvar::from_account_info`] to access its data, as in this example that
//! again logs the [`clock`] sysvar.
//!
//! ```
//! use solana_program::{
//! account_info::{next_account_info, AccountInfo},
//! clock,
//! entrypoint::ProgramResult,
//! msg,
//! pubkey::Pubkey,
//! sysvar::Sysvar,
//! };
//!
//! fn process_instruction(
//! program_id: &Pubkey,
//! accounts: &[AccountInfo],
//! instruction_data: &[u8],
//! ) -> ProgramResult {
//! let account_info_iter = &mut accounts.iter();
//! let clock_account = next_account_info(account_info_iter)?;
//! let clock = clock::Clock::from_account_info(&clock_account)?;
//! msg!("clock: {:#?}", clock);
//! Ok(())
//! }
//! ```
//!
//! When possible, programs should prefer to call `Sysvar::get` instead of
//! deserializing with `Sysvar::from_account_info`, as the latter imposes extra
//! overhead of deserialization while also requiring the sysvar account address
//! be passed to the program, wasting the limited space available to
//! transactions. Deserializing sysvars that can instead be retrieved with
//! `Sysvar::get` should be only be considered for compatibility with older
//! programs that pass around sysvar accounts.
//!
//! Some sysvars are too large to deserialize within a program, and
//! `Sysvar::from_account_info` returns an error, or the serialization attempt
//! will exhaust the program's compute budget. Some sysvars do not implement
//! `Sysvar::get` and return an error. Some sysvars have custom deserializers
//! that do not implement the `Sysvar` trait. These cases are documented in the
//! modules for individual sysvars.
//!
//! All sysvar accounts are owned by the account identified by [`sysvar::ID`].
//!
//! [`sysvar::ID`]: crate::sysvar::ID
//!
//! For more details see the Solana [documentation on sysvars][sysvardoc].
//!
//! [sysvardoc]: https://docs.solana.com/developing/runtime-facilities/sysvars
@ -37,6 +114,7 @@ lazy_static! {
];
}
/// Returns `true` of the given `Pubkey` is a sysvar account.
pub fn is_sysvar_id(id: &Pubkey) -> bool {
ALL_IDS.iter().any(|key| key == id)
}
@ -94,35 +172,54 @@ macro_rules! declare_deprecated_sysvar_id(
// Owner pubkey for sysvar accounts
crate::declare_id!("Sysvar1111111111111111111111111111111111111");
/// A type that holds sysvar data and has an associated sysvar `Pubkey`.
pub trait SysvarId {
/// The `Pubkey` of the sysvar.
fn id() -> Pubkey;
/// Returns `true` if the given pubkey is the program ID.
fn check_id(pubkey: &Pubkey) -> bool;
}
// Sysvar utilities
/// A type that holds sysvar data.
pub trait Sysvar:
SysvarId + Default + Sized + serde::Serialize + serde::de::DeserializeOwned
{
/// The size in bytes of the sysvar as serialized account data.
fn size_of() -> usize {
bincode::serialized_size(&Self::default()).unwrap() as usize
}
/// Deserializes a sysvar from its `AccountInfo`.
/// Deserializes the sysvar from its `AccountInfo`.
///
/// # Errors
///
/// If `account_info` does not have the same ID as the sysvar
/// this function returns [`ProgramError::InvalidArgument`].
/// If `account_info` does not have the same ID as the sysvar this function
/// returns [`ProgramError::InvalidArgument`].
fn from_account_info(account_info: &AccountInfo) -> Result<Self, ProgramError> {
if !Self::check_id(account_info.unsigned_key()) {
return Err(ProgramError::InvalidArgument);
}
bincode::deserialize(&account_info.data.borrow()).map_err(|_| ProgramError::InvalidArgument)
}
/// Serializes the sysvar to `AccountInfo`.
///
/// # Errors
///
/// Returns `None` if serialization failed.
fn to_account_info(&self, account_info: &mut AccountInfo) -> Option<()> {
bincode::serialize_into(&mut account_info.data.borrow_mut()[..], self).ok()
}
/// Load the sysvar directly from the runtime.
///
/// This is the preferred way to load a sysvar. Calling this method does not
/// incur any deserialization overhead, and does not require the sysvar
/// account to be passed to the program.
///
/// Not all sysvars support this method. If not, it returns
/// [`ProgramError::UnsupportedSysvar`].
fn get() -> Result<Self, ProgramError> {
Err(ProgramError::UnsupportedSysvar)
}

View File

@ -1,3 +1,21 @@
//! Information about recent blocks and their fee calculators.
//!
//! The _recent blockhashes sysvar_ provides access to the [`RecentBlockhashes`],
//! which contains recent blockhahes and their [`FeeCalculator`]s.
//!
//! [`RecentBlockhashes`] does not implement [`Sysvar::get`].
//!
//! This sysvar is deprecated and should not be used. Transaction fees should be
//! determined with the [`getFeeForMessage`] RPC method. For additional context
//! see the [Comprehensive Compute Fees proposal][ccf].
//!
//! [`getFeeForMessage`]: https://docs.solana.com/developing/clients/jsonrpc-api#getfeeformessage
//! [ccf]: https://docs.solana.com/proposals/comprehensive-compute-fees
//!
//! See also the Solana [documentation on the recent blockhashes sysvar][sdoc].
//!
//! [sdoc]: https://docs.solana.com/developing/runtime-facilities/sysvars#recentblockhashes
#![allow(deprecated)]
#![allow(clippy::integer_arithmetic)]
use {

View File

@ -1,5 +1,131 @@
//! This account contains the current cluster rent
//! Configuration for network [rent].
//!
//! [rent]: https://docs.solana.com/implemented-proposals/rent
//!
//! The _rent sysvar_ provides access to the [`Rent`] type, which defines
//! storage rent fees.
//!
//! [`Rent`] implements [`Sysvar::get`] and can be loaded efficiently without
//! passing the sysvar account ID to the program.
//!
//! See also the Solana [documentation on the rent sysvar][sdoc].
//!
//! [sdoc]: https://docs.solana.com/developing/runtime-facilities/sysvars#rent
//!
//! # Examples
//!
//! Accessing via on-chain program directly:
//!
//! ```no_run
//! # use solana_program::{
//! # account_info::{AccountInfo, next_account_info},
//! # entrypoint::ProgramResult,
//! # msg,
//! # pubkey::Pubkey,
//! # sysvar::rent::{self, Rent},
//! # sysvar::Sysvar,
//! # };
//! # use solana_program::program_error::ProgramError;
//! #
//! fn process_instruction(
//! program_id: &Pubkey,
//! accounts: &[AccountInfo],
//! instruction_data: &[u8],
//! ) -> ProgramResult {
//!
//! let rent = Rent::get()?;
//! msg!("rent: {:#?}", rent);
//!
//! Ok(())
//! }
//! #
//! # use solana_program::sysvar::SysvarId;
//! # let p = Rent::id();
//! # let l = &mut 1009200;
//! # let d = &mut vec![152, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 100];
//! # let a = AccountInfo::new(&p, false, false, l, d, &p, false, 0);
//! # let accounts = &[a.clone(), a];
//! # process_instruction(
//! # &Pubkey::new_unique(),
//! # accounts,
//! # &[],
//! # )?;
//! # Ok::<(), ProgramError>(())
//! ```
//!
//! Accessing via on-chain program's parameters:
//!
//! ```
//! # use solana_program::{
//! # account_info::{AccountInfo, next_account_info},
//! # entrypoint::ProgramResult,
//! # msg,
//! # pubkey::Pubkey,
//! # sysvar::rent::{self, Rent},
//! # sysvar::Sysvar,
//! # };
//! # use solana_program::program_error::ProgramError;
//! #
//! fn process_instruction(
//! program_id: &Pubkey,
//! accounts: &[AccountInfo],
//! instruction_data: &[u8],
//! ) -> ProgramResult {
//! let account_info_iter = &mut accounts.iter();
//! let rent_account_info = next_account_info(account_info_iter)?;
//!
//! assert!(rent::check_id(rent_account_info.key));
//!
//! let rent = Rent::from_account_info(rent_account_info)?;
//! msg!("rent: {:#?}", rent);
//!
//! Ok(())
//! }
//! #
//! # use solana_program::sysvar::SysvarId;
//! # let p = Rent::id();
//! # let l = &mut 1009200;
//! # let d = &mut vec![152, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 100];
//! # let a = AccountInfo::new(&p, false, false, l, d, &p, false, 0);
//! # let accounts = &[a.clone(), a];
//! # process_instruction(
//! # &Pubkey::new_unique(),
//! # accounts,
//! # &[],
//! # )?;
//! # Ok::<(), ProgramError>(())
//! ```
//!
//! Accessing via the RPC client:
//!
//! ```
//! # use solana_program::example_mocks::solana_sdk;
//! # use solana_program::example_mocks::solana_client;
//! # use solana_sdk::account::Account;
//! # use solana_client::rpc_client::RpcClient;
//! # use solana_sdk::sysvar::rent::{self, Rent};
//! # use anyhow::Result;
//! #
//! fn print_sysvar_rent(client: &RpcClient) -> Result<()> {
//! # client.set_get_account_response(rent::ID, Account {
//! # lamports: 1009200,
//! # data: vec![152, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 64, 100],
//! # owner: solana_sdk::system_program::ID,
//! # executable: false,
//! # rent_epoch: 307,
//! # });
//! #
//! let rent = client.get_account(&rent::ID)?;
//! let data: Rent = bincode::deserialize(&rent.data)?;
//!
//! Ok(())
//! }
//! #
//! # let client = RpcClient::new(String::new());
//! # print_sysvar_rent(&client)?;
//! #
//! # Ok::<(), anyhow::Error>(())
//! ```
pub use crate::rent::Rent;
use crate::{impl_sysvar_get, program_error::ProgramError, sysvar::Sysvar};

View File

@ -1,5 +1,5 @@
//! DEPRECATED: This sysvar can be removed once the pico-inflation feature is enabled
//!
//! This sysvar is deprecated and unused.
use crate::sysvar::Sysvar;
crate::declare_sysvar_id!("SysvarRewards111111111111111111111111111111", Rewards);

View File

@ -1,7 +1,50 @@
//! named accounts for synthesized data accounts for bank state, etc.
//! The most recent hashes of a slot's parent banks.
//!
//! this account carries the Bank's most recent bank hashes for some N parents
//! The _slot hashes sysvar_ provides access to the [`SlotHashes`] type.
//!
//! The [`Sysvar::from_account_info`] and [`Sysvar::get`] methods always return
//! [`ProgramError::UnsupportedSysvar`] because this sysvar account is too large
//! to process on-chain. Thus this sysvar cannot be accessed on chain, though
//! one can still use the [`SysvarId::id`], [`SysvarId::check_id`] and
//! [`Sysvar::size_of`] methods in an on-chain program, and it can be accessed
//! off-chain through RPC.
//!
//! [`SysvarId::id`]: crate::sysvar::SysvarId::id
//! [`SysvarId::check_id`]: crate::sysvar::SysvarId::check_id
//!
//! # Examples
//!
//! Calling via the RPC client:
//!
//! ```
//! # use solana_program::example_mocks::solana_sdk;
//! # use solana_program::example_mocks::solana_client;
//! # use solana_sdk::account::Account;
//! # use solana_client::rpc_client::RpcClient;
//! # use solana_sdk::sysvar::slot_hashes::{self, SlotHashes};
//! # use anyhow::Result;
//! #
//! fn print_sysvar_slot_hashes(client: &RpcClient) -> Result<()> {
//! # client.set_get_account_response(slot_hashes::ID, Account {
//! # lamports: 1009200,
//! # data: vec![1, 0, 0, 0, 0, 0, 0, 0, 86, 190, 235, 7, 0, 0, 0, 0, 133, 242, 94, 158, 223, 253, 207, 184, 227, 194, 235, 27, 176, 98, 73, 3, 175, 201, 224, 111, 21, 65, 73, 27, 137, 73, 229, 19, 255, 192, 193, 126],
//! # owner: solana_sdk::system_program::ID,
//! # executable: false,
//! # rent_epoch: 307,
//! # });
//! #
//! let slot_hashes = client.get_account(&slot_hashes::ID)?;
//! let data: SlotHashes = bincode::deserialize(&slot_hashes.data)?;
//!
//! Ok(())
//! }
//! #
//! # let client = RpcClient::new(String::new());
//! # print_sysvar_slot_hashes(&client)?;
//! #
//! # Ok::<(), anyhow::Error>(())
//! ```
pub use crate::slot_hashes::SlotHashes;
use crate::{account_info::AccountInfo, program_error::ProgramError, sysvar::Sysvar};

View File

@ -1,8 +1,52 @@
//! named accounts for synthesized data accounts for bank state, etc.
//! A bitvector of slots present over the last epoch.
//!
//! this account carries a bitvector of slots present over the past
//! epoch
//! The _slot history sysvar_ provides access to the [`SlotHistory`] type.
//!
//! The [`Sysvar::from_account_info`] and [`Sysvar::get`] methods always return
//! [`ProgramError::UnsupportedSysvar`] because this sysvar account is too large
//! to process on-chain. Thus this sysvar cannot be accessed on chain, though
//! one can still use the [`SysvarId::id`], [`SysvarId::check_id`] and
//! [`Sysvar::size_of`] methods in an on-chain program, and it can be accessed
//! off-chain through RPC.
//!
//! [`SysvarId::id`]: crate::sysvar::SysvarId::id
//! [`SysvarId::check_id`]: crate::sysvar::SysvarId::check_id
//!
//! # Examples
//!
//! Calling via the RPC client:
//!
//! ```
//! # use solana_program::example_mocks::solana_sdk;
//! # use solana_program::example_mocks::solana_client;
//! # use solana_sdk::account::Account;
//! # use solana_client::rpc_client::RpcClient;
//! # use solana_sdk::sysvar::slot_history::{self, SlotHistory};
//! # use anyhow::Result;
//! #
//! fn print_sysvar_slot_history(client: &RpcClient) -> Result<()> {
//! # let slot_history = SlotHistory::default();
//! # let data: Vec<u8> = bincode::serialize(&slot_history)?;
//! # client.set_get_account_response(slot_history::ID, Account {
//! # lamports: 913326000,
//! # data,
//! # owner: solana_sdk::system_program::ID,
//! # executable: false,
//! # rent_epoch: 307,
//! # });
//! #
//! let slot_history = client.get_account(&slot_history::ID)?;
//! let data: SlotHistory = bincode::deserialize(&slot_history.data)?;
//!
//! Ok(())
//! }
//! #
//! # let client = RpcClient::new(String::new());
//! # print_sysvar_slot_history(&client)?;
//! #
//! # Ok::<(), anyhow::Error>(())
//! ```
use crate::sysvar::Sysvar;
pub use crate::{
account_info::AccountInfo, program_error::ProgramError, slot_history::SlotHistory,

View File

@ -1,7 +1,50 @@
//! named accounts for synthesized data accounts for bank state, etc.
//! History of stake activations and de-activations.
//!
//! this account carries history about stake activations and de-activations
//! The _stake history sysvar_ provides access to the [`StakeHistory`] type.
//!
//! The [`Sysvar::get`] method always returns
//! [`ProgramError::UnsupportedSysvar`], and in practice the data size of this
//! sysvar is too large to process on chain. One can still use the
//! [`SysvarId::id`], [`SysvarId::check_id`] and [`Sysvar::size_of`] methods in
//! an on-chain program, and it can be accessed off-chain through RPC.
//!
//! [`ProgramError::UnsupportedSysvar`]: crate::program_error::ProgramError::UnsupportedSysvar
//! [`SysvarId::id`]: crate::sysvar::SysvarId::id
//! [`SysvarId::check_id`]: crate::sysvar::SysvarId::check_id
//!
//! # Examples
//!
//! Calling via the RPC client:
//!
//! ```
//! # use solana_program::example_mocks::solana_sdk;
//! # use solana_program::example_mocks::solana_client;
//! # use solana_sdk::account::Account;
//! # use solana_client::rpc_client::RpcClient;
//! # use solana_sdk::sysvar::stake_history::{self, StakeHistory};
//! # use anyhow::Result;
//! #
//! fn print_sysvar_stake_history(client: &RpcClient) -> Result<()> {
//! # client.set_get_account_response(stake_history::ID, Account {
//! # lamports: 114979200,
//! # data: vec![0, 0, 0, 0, 0, 0, 0, 0],
//! # owner: solana_sdk::system_program::ID,
//! # executable: false,
//! # rent_epoch: 307,
//! # });
//! #
//! let stake_history = client.get_account(&stake_history::ID)?;
//! let data: StakeHistory = bincode::deserialize(&stake_history.data)?;
//!
//! Ok(())
//! }
//! #
//! # let client = RpcClient::new(String::new());
//! # print_sysvar_stake_history(&client)?;
//! #
//! # Ok::<(), anyhow::Error>(())
//! ```
pub use crate::stake_history::StakeHistory;
use crate::sysvar::Sysvar;