Skip to content

Commit

Permalink
syscall: get-epoch-stake
Browse files Browse the repository at this point in the history
  • Loading branch information
buffalojoec committed May 6, 2024
1 parent ca8328f commit 30d91b1
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 2 deletions.
68 changes: 66 additions & 2 deletions programs/bpf_loader/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,9 @@ use {
disable_deploy_of_alloc_free_syscall, disable_fees_sysvar,
enable_alt_bn128_compression_syscall, enable_alt_bn128_syscall,
enable_big_mod_exp_syscall, enable_partitioned_epoch_reward, enable_poseidon_syscall,
error_on_syscall_bpf_function_hash_collisions, last_restart_slot_sysvar,
reject_callx_r10, remaining_compute_units_syscall_enabled, switch_to_new_elf_parser,
enable_syscall_get_epoch_stake, error_on_syscall_bpf_function_hash_collisions,
last_restart_slot_sysvar, reject_callx_r10, remaining_compute_units_syscall_enabled,
switch_to_new_elf_parser,
},
hash::{Hash, Hasher},
instruction::{AccountMeta, InstructionError, ProcessedSiblingInstruction},
Expand Down Expand Up @@ -278,6 +279,8 @@ pub fn create_program_runtime_environment_v1<'a>(
let enable_poseidon_syscall = feature_set.is_active(&enable_poseidon_syscall::id());
let remaining_compute_units_syscall_enabled =
feature_set.is_active(&remaining_compute_units_syscall_enabled::id());
let enable_syscall_get_epoch_stake =
feature_set.is_active(&enable_syscall_get_epoch_stake::id());
// !!! ATTENTION !!!
// When adding new features for RBPF here,
// also add them to `Bank::apply_builtin_program_feature_transitions()`.
Expand Down Expand Up @@ -464,6 +467,14 @@ pub fn create_program_runtime_environment_v1<'a>(
SyscallAltBn128Compression::vm,
)?;

// Get Epoch Stake
register_feature_gated_function!(
result,
enable_syscall_get_epoch_stake,
*b"sol_syscall_get_epoch_stake",
SyscallGetEpochStake::vm,
)?;

// Log data
result.register_function_hashed(*b"sol_log_data", SyscallLogData::vm)?;

Expand Down Expand Up @@ -1997,6 +2008,59 @@ declare_builtin_function!(
}
);

declare_builtin_function!(
// Get Epoch Stake Syscall
SyscallGetEpochStake,
fn rust(
invoke_context: &mut InvokeContext,
vote_address: u64,
_arg2: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
memory_mapping: &mut MemoryMapping,
) -> Result<u64, Error> {
// Compute units, as specified by SIMD-0133.
// cu = syscall_base_cost
// + floor(32/cpi_bytes_per_unit)
// + mem_op_base_cost
let compute_budget = invoke_context.get_compute_budget();
let compute_units = compute_budget
.syscall_base_cost
.saturating_add(
32u64
.checked_div(compute_budget.cpi_bytes_per_unit)
.unwrap_or(u64::MAX),
)
.saturating_add(compute_budget.mem_op_base_cost);

consume_compute_meter(invoke_context, compute_units)?;

// Control flow, as specified by SIMD-0133.
// * The syscall aborts the virtual machine if not all bytes in VM
// memory range `[vote_addr, vote_addr + 32)` are readable.
// * Otherwise, the syscall returns a `u64` integer representing the
// total active stake delegated to the vote account at the provided
// address.
// * If the provided vote address corresponds to an account that is
// not a vote account or does not exist, the syscall will return
// `0` for active stake.
let check_aligned = invoke_context.get_check_aligned();
let vote_address = translate_type::<Pubkey>(memory_mapping, vote_address, check_aligned)?;

Ok(
if let Some(vote_accounts) = invoke_context.get_epoch_vote_accounts() {
vote_accounts
.get(vote_address)
.map(|(stake, _)| *stake)
.unwrap_or(0)
} else {
0
},
)
}
);

#[cfg(test)]
#[allow(clippy::arithmetic_side_effects)]
#[allow(clippy::indexing_slicing)]
Expand Down
17 changes: 17 additions & 0 deletions sdk/program/src/epoch_stake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use crate::pubkey::Pubkey;

/// Get the current epoch stake for a given vote address.
///
/// If the provided vote address corresponds to an account that is not a vote
/// account or does not exist, returns `0` for active stake.
pub fn get_epoch_stake(vote_address: &Pubkey) -> u64 {
let vote_address = vote_address as *const _ as *const u8;

#[cfg(target_os = "solana")]
let result = unsafe { crate::syscalls::sol_syscall_get_epoch_stake(vote_address) };

#[cfg(not(target_os = "solana"))]
let result = crate::program_stubs::sol_syscall_get_epoch_stake(vote_address);

result
}
1 change: 1 addition & 0 deletions sdk/program/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ pub mod entrypoint;
pub mod entrypoint_deprecated;
pub mod epoch_rewards;
pub mod epoch_schedule;
pub mod epoch_stake;
pub mod feature;
pub mod fee_calculator;
pub mod hash;
Expand Down
10 changes: 10 additions & 0 deletions sdk/program/src/program_stubs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ pub trait SyscallStubs: Sync + Send {
fn sol_get_last_restart_slot(&self, _var_addr: *mut u8) -> u64 {
UNSUPPORTED_SYSVAR
}
fn sol_syscall_get_epoch_stake(&self, _vote_address: *const u8) -> u64 {
0
}
/// # Safety
unsafe fn sol_memcpy(&self, dst: *mut u8, src: *const u8, n: usize) {
// cannot be overlapping
Expand Down Expand Up @@ -171,6 +174,13 @@ pub(crate) fn sol_get_last_restart_slot(var_addr: *mut u8) -> u64 {
.sol_get_last_restart_slot(var_addr)
}

pub(crate) fn sol_syscall_get_epoch_stake(vote_address: *const u8) -> u64 {
SYSCALL_STUBS
.read()
.unwrap()
.sol_syscall_get_epoch_stake(vote_address)
}

pub(crate) fn sol_memcpy(dst: *mut u8, src: *const u8, n: usize) {
unsafe {
SYSCALL_STUBS.read().unwrap().sol_memcpy(dst, src, n);
Expand Down
1 change: 1 addition & 0 deletions sdk/program/src/syscalls/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ define_syscall!(fn sol_get_epoch_rewards_sysvar(addr: *mut u8) -> u64);
define_syscall!(fn sol_poseidon(parameters: u64, endianness: u64, vals: *const u8, val_len: u64, hash_result: *mut u8) -> u64);
define_syscall!(fn sol_remaining_compute_units() -> u64);
define_syscall!(fn sol_alt_bn128_compression(op: u64, input: *const u8, input_size: u64, result: *mut u8) -> u64);
define_syscall!(fn sol_syscall_get_epoch_stake(vote_address: *const u8) -> u64);

#[cfg(target_feature = "static-syscalls")]
pub const fn sys_hash(name: &str) -> usize {
Expand Down

0 comments on commit 30d91b1

Please sign in to comment.