Skip to content

Commit

Permalink
syscall: get-epoch-stake: tests
Browse files Browse the repository at this point in the history
  • Loading branch information
buffalojoec committed May 4, 2024
1 parent 6a5aaf5 commit 52f6e22
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 2 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion program-runtime/src/invoke_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ use {
solana_vote::vote_account::VoteAccountsHashMap,
std::{
alloc::Layout,
cell::RefCell,
cell::{Ref, RefCell},
fmt::{self, Debug},
rc::Rc,
sync::{atomic::Ordering, Arc},
Expand Down Expand Up @@ -598,6 +598,11 @@ impl<'a> InvokeContext<'a> {
&self.current_compute_budget
}

/// Get this invocation's compute meter.
pub fn get_compute_meter(&self) -> Ref<u64> {
self.compute_meter.borrow()
}

/// Get the current feature set.
pub fn get_feature_set(&self) -> &FeatureSet {
&self.environment_config.feature_set
Expand Down
1 change: 1 addition & 0 deletions programs/bpf_loader/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ assert_matches = { workspace = true }
memoffset = { workspace = true }
rand = { workspace = true }
solana-sdk = { workspace = true, features = ["dev-context-only-utils"] }
solana-vote = { workspace = true }
test-case = { workspace = true }

[lib]
Expand Down
157 changes: 156 additions & 1 deletion programs/bpf_loader/src/syscalls/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2088,7 +2088,8 @@ mod tests {
self, clock::Clock, epoch_rewards::EpochRewards, epoch_schedule::EpochSchedule,
},
},
std::{mem, str::FromStr},
solana_vote::vote_account::VoteAccount,
std::{collections::HashMap, mem, str::FromStr},
};

macro_rules! assert_access_violation {
Expand Down Expand Up @@ -4261,6 +4262,160 @@ mod tests {
}
}

#[test]
fn test_syscall_get_epoch_stake() {
let config = Config::default();
let compute_budget = ComputeBudget::default();
let sysvar_cache = Arc::<SysvarCache>::default();

let expected_epoch_stake = 55_000_000_000u64;
let expected_cus = compute_budget.syscall_base_cost
+ 32 / compute_budget.cpi_bytes_per_unit
+ compute_budget.mem_op_base_cost;

let vote_address = Pubkey::new_unique();
let mut vote_accounts_map = HashMap::new();
vote_accounts_map.insert(
vote_address,
(
expected_epoch_stake,
VoteAccount::try_from(AccountSharedData::new(
0,
0,
&solana_sdk::vote::program::id(),
))
.unwrap(),
),
);

with_mock_invoke_context!(invoke_context, transaction_context, vec![]);
invoke_context.environment_config = EnvironmentConfig::new(
Hash::default(),
Arc::<FeatureSet>::default(),
0,
Some(&vote_accounts_map),
&sysvar_cache,
);

{
// The syscall aborts the virtual machine if not all bytes in VM
// memory range `[vote_addr, vote_addr + 32)` are readable.
let vote_address_var = 0x100000000;

let mut memory_mapping = MemoryMapping::new(
vec![
// Invalid read-only memory region.
MemoryRegion::new_readonly(&[2; 31], vote_address_var),
],
&config,
&SBPFVersion::V2,
)
.unwrap();

let result = SyscallGetEpochStake::rust(
&mut invoke_context,
vote_address_var,
0,
0,
0,
0,
&mut memory_mapping,
);

assert_access_violation!(result, vote_address_var, 32);

// Compute units, as specified by SIMD-0133.
// cu = syscall_base_cost
// + floor(32/cpi_bytes_per_unit)
// + mem_op_base_cost
assert_eq!(
invoke_context.get_compute_meter().to_owned(),
compute_budget.compute_unit_limit - expected_cus
);
}

invoke_context.mock_set_remaining(compute_budget.compute_unit_limit);
{
// Otherwise, the syscall returns a `u64` integer representing the
// total active stake delegated to the vote account at the provided
// address.
let vote_address_var = 0x100000000;

let mut memory_mapping = MemoryMapping::new(
vec![MemoryRegion::new_readonly(
bytes_of(&vote_address),
vote_address_var,
)],
&config,
&SBPFVersion::V2,
)
.unwrap();

let result = SyscallGetEpochStake::rust(
&mut invoke_context,
vote_address_var,
0,
0,
0,
0,
&mut memory_mapping,
)
.unwrap();

assert_eq!(result, expected_epoch_stake);

// Compute units, as specified by SIMD-0133.
// cu = syscall_base_cost
// + floor(32/cpi_bytes_per_unit)
// + mem_op_base_cost
assert_eq!(
invoke_context.get_compute_meter().to_owned(),
compute_budget.compute_unit_limit - expected_cus
);
}

invoke_context.mock_set_remaining(compute_budget.compute_unit_limit);
{
// If the provided vote address corresponds to an account that is
// not a vote account or does not exist, the syscall will write
// `0` for active stake.
let vote_address_var = 0x100000000;
let not_a_vote_address = Pubkey::new_unique(); // Not a vote account.

let mut memory_mapping = MemoryMapping::new(
vec![MemoryRegion::new_readonly(
bytes_of(&not_a_vote_address),
vote_address_var,
)],
&config,
&SBPFVersion::V2,
)
.unwrap();

let result = SyscallGetEpochStake::rust(
&mut invoke_context,
vote_address_var,
0,
0,
0,
0,
&mut memory_mapping,
)
.unwrap();

assert_eq!(result, 0); // `0` for active stake.

// Compute units, as specified by SIMD-0133.
// cu = syscall_base_cost
// + floor(32/cpi_bytes_per_unit)
// + mem_op_base_cost
assert_eq!(
invoke_context.get_compute_meter().to_owned(),
compute_budget.compute_unit_limit - expected_cus
);
}
}

#[test]
fn test_check_type_assumptions() {
check_type_assumptions();
Expand Down

0 comments on commit 52f6e22

Please sign in to comment.