Add epoch_rewards syscalls (#32159)

Co-authored-by: HaoranYi <haoran.yi@solana.com>
This commit is contained in:
HaoranYi 2023-06-27 09:14:43 -05:00 committed by GitHub
parent 6f72258e3e
commit b12180b863
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 123 additions and 9 deletions

View File

@ -15,7 +15,9 @@ use {
slot_hashes::SlotHashes,
slot_history::{self, SlotHistory},
stake_history::{StakeHistory, StakeHistoryEntry},
sysvar::{self, last_restart_slot::LastRestartSlot, rewards::Rewards},
sysvar::{
self, epoch_rewards::EpochRewards, last_restart_slot::LastRestartSlot, rewards::Rewards,
},
},
};
@ -89,6 +91,10 @@ pub fn parse_sysvar(data: &[u8], pubkey: &Pubkey) -> Result<SysvarAccountType, P
let last_restart_slot = last_restart_slot.last_restart_slot;
SysvarAccountType::LastRestartSlot(UiLastRestartSlot { last_restart_slot })
})
} else if pubkey == &sysvar::epoch_rewards::id() {
deserialize::<EpochRewards>(data)
.ok()
.map(SysvarAccountType::EpochRewards)
} else {
None
}
@ -113,6 +119,7 @@ pub enum SysvarAccountType {
SlotHistory(UiSlotHistory),
StakeHistory(Vec<UiStakeHistoryEntry>),
LastRestartSlot(UiLastRestartSlot),
EpochRewards(EpochRewards),
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Default)]
@ -363,5 +370,16 @@ mod test {
last_restart_slot: 1282
})
);
let epoch_rewards = EpochRewards {
total_rewards: 100,
distributed_rewards: 20,
distribution_complete_block_height: 42,
};
let epoch_rewards_sysvar = create_account_for_test(&epoch_rewards);
assert_eq!(
parse_sysvar(&epoch_rewards_sysvar.data, &sysvar::epoch_rewards::id()).unwrap(),
SysvarAccountType::EpochRewards(epoch_rewards),
);
}
}

View File

@ -5,8 +5,8 @@ pub use self::{
},
mem_ops::{SyscallMemcmp, SyscallMemcpy, SyscallMemmove, SyscallMemset},
sysvar::{
SyscallGetClockSysvar, SyscallGetEpochScheduleSysvar, SyscallGetFeesSysvar,
SyscallGetLastRestartSlotSysvar, SyscallGetRentSysvar,
SyscallGetClockSysvar, SyscallGetEpochRewardsSysvar, SyscallGetEpochScheduleSysvar,
SyscallGetFeesSysvar, SyscallGetLastRestartSlotSysvar, SyscallGetRentSysvar,
},
};
#[allow(deprecated)]
@ -36,7 +36,7 @@ use {
self, blake3_syscall_enabled, curve25519_syscall_enabled,
disable_cpi_setting_executable_and_rent_epoch, disable_deploy_of_alloc_free_syscall,
disable_fees_sysvar, enable_alt_bn128_syscall, enable_big_mod_exp_syscall,
enable_early_verification_of_account_modifications,
enable_early_verification_of_account_modifications, enable_partitioned_epoch_reward,
error_on_syscall_bpf_function_hash_collisions, last_restart_slot_sysvar,
libsecp256k1_0_5_upgrade_enabled, reject_callx_r10,
stop_sibling_instruction_search_at_parent, stop_truncating_strings_in_syscalls,
@ -186,6 +186,8 @@ pub fn create_program_runtime_environment<'a>(
let blake3_syscall_enabled = feature_set.is_active(&blake3_syscall_enabled::id());
let curve25519_syscall_enabled = feature_set.is_active(&curve25519_syscall_enabled::id());
let disable_fees_sysvar = feature_set.is_active(&disable_fees_sysvar::id());
let epoch_rewards_syscall_enabled =
feature_set.is_active(&enable_partitioned_epoch_reward::id());
let disable_deploy_of_alloc_free_syscall = reject_deployment_of_broken_elfs
&& feature_set.is_active(&disable_deploy_of_alloc_free_syscall::id());
let last_restart_slot_syscall_enabled = feature_set.is_active(&last_restart_slot_sysvar::id());
@ -272,6 +274,13 @@ pub fn create_program_runtime_environment<'a>(
SyscallGetLastRestartSlotSysvar::call,
)?;
register_feature_gated_function!(
result,
epoch_rewards_syscall_enabled,
b"sol_get_epoch_rewrds_sysvar",
SyscallGetEpochRewardsSysvar::call,
)?;
// Memory ops
result.register_function(b"sol_memcpy_", SyscallMemcpy::call)?;
result.register_function(b"sol_memmove_", SyscallMemmove::call)?;
@ -1807,7 +1816,9 @@ mod tests {
instruction::Instruction,
program::check_type_assumptions,
stable_layout::stable_instruction::StableInstruction,
sysvar::{self, clock::Clock, epoch_schedule::EpochSchedule},
sysvar::{
self, clock::Clock, epoch_rewards::EpochRewards, epoch_schedule::EpochSchedule,
},
},
std::{mem, str::FromStr},
};
@ -3177,11 +3188,17 @@ mod tests {
src_rent.exemption_threshold = 2.0;
src_rent.burn_percent = 3;
let mut src_rewards = create_filled_type::<EpochRewards>(false);
src_rewards.total_rewards = 100;
src_rewards.distributed_rewards = 10;
src_rewards.distribution_complete_block_height = 42;
let mut sysvar_cache = SysvarCache::default();
sysvar_cache.set_clock(src_clock.clone());
sysvar_cache.set_epoch_schedule(src_epochschedule);
sysvar_cache.set_fees(src_fees.clone());
sysvar_cache.set_rent(src_rent);
sysvar_cache.set_epoch_rewards(src_rewards);
let transaction_accounts = vec![
(
@ -3200,6 +3217,10 @@ mod tests {
sysvar::rent::id(),
create_account_shared_data_for_test(&src_rent),
),
(
sysvar::epoch_rewards::id(),
create_account_shared_data_for_test(&src_rewards),
),
];
with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
@ -3345,6 +3366,42 @@ mod tests {
clean_rent.burn_percent = src_rent.burn_percent;
assert!(are_bytes_equal(&got_rent, &clean_rent));
}
// Test epoch rewards sysvar
{
let mut got_rewards = create_filled_type::<EpochRewards>(true);
let got_rewards_va = 0x100000000;
let mut memory_mapping = MemoryMapping::new(
vec![MemoryRegion::new_writable(
bytes_of_mut(&mut got_rewards),
got_rewards_va,
)],
&config,
)
.unwrap();
let mut result = ProgramResult::Ok(0);
SyscallGetEpochRewardsSysvar::call(
&mut invoke_context,
got_rewards_va,
0,
0,
0,
0,
&mut memory_mapping,
&mut result,
);
result.unwrap();
assert_eq!(got_rewards, src_rewards);
let mut clean_rewards = create_filled_type::<EpochRewards>(true);
clean_rewards.total_rewards = src_rewards.total_rewards;
clean_rewards.distributed_rewards = src_rewards.distributed_rewards;
clean_rewards.distribution_complete_block_height =
src_rewards.distribution_complete_block_height;
assert!(are_bytes_equal(&got_rewards, &clean_rewards));
}
}
fn call_program_address_common<'a, 'b: 'a>(

View File

@ -66,6 +66,28 @@ declare_syscall!(
}
);
declare_syscall!(
/// Get a EpochRewards sysvar
SyscallGetEpochRewardsSysvar,
fn inner_call(
invoke_context: &mut InvokeContext,
var_addr: u64,
_arg2: u64,
_arg3: u64,
_arg4: u64,
_arg5: u64,
memory_mapping: &mut MemoryMapping,
) -> Result<u64, Error> {
get_sysvar(
invoke_context.get_sysvar_cache().get_epoch_rewards(),
var_addr,
invoke_context.get_check_aligned(),
memory_mapping,
invoke_context,
)
}
);
declare_syscall!(
/// Get a Fees sysvar
SyscallGetFeesSysvar,

View File

@ -13,8 +13,9 @@ use solana_program::{
program_error::ProgramError,
pubkey::Pubkey,
sysvar::{
self, clock::Clock, epoch_schedule::EpochSchedule, instructions, rent::Rent,
slot_hashes::SlotHashes, slot_history::SlotHistory, stake_history::StakeHistory, Sysvar,
self, clock::Clock, epoch_rewards::EpochRewards, epoch_schedule::EpochSchedule,
instructions, rent::Rent, slot_hashes::SlotHashes, slot_history::SlotHistory,
stake_history::StakeHistory, Sysvar,
},
};
@ -69,6 +70,7 @@ pub fn process_instruction(
AccountMeta::new_readonly(*accounts[8].key, false),
AccountMeta::new_readonly(*accounts[9].key, false),
AccountMeta::new_readonly(*accounts[10].key, false),
AccountMeta::new_readonly(*accounts[11].key, false),
],
)
);
@ -123,5 +125,18 @@ pub fn process_instruction(
assert_eq!(fees, got_fees);
}
// Epoch Rewards
{
msg!("EpochRewards identifier:");
sysvar::epoch_rewards::id().log();
let epoch_rewards = EpochRewards::from_account_info(&accounts[11]);
// epoch_rewards sysvar should only be valid during epoch reward period. In this test case,
// the test bank is outside reward period. Therefore, we expect that the epoch_rewards
// sysvar doesn't exist.
assert!(epoch_rewards.is_err());
let got_epoch_rewards = EpochRewards::get();
assert!(got_epoch_rewards.is_err());
}
Ok(())
}

View File

@ -9,8 +9,8 @@ use {
pubkey::Pubkey,
signature::Signer,
sysvar::{
clock, epoch_schedule, fees, instructions, recent_blockhashes, rent, slot_hashes,
slot_history, stake_history,
clock, epoch_rewards, epoch_schedule, fees, instructions, recent_blockhashes, rent,
slot_hashes, slot_history, stake_history,
},
transaction::Transaction,
},
@ -45,6 +45,7 @@ async fn test_sysvars() {
AccountMeta::new_readonly(stake_history::id(), false),
#[allow(deprecated)]
AccountMeta::new_readonly(fees::id(), false),
AccountMeta::new_readonly(epoch_rewards::id(), false),
],
)],
Some(&payer.pubkey()),
@ -78,6 +79,7 @@ async fn test_sysvars() {
AccountMeta::new_readonly(stake_history::id(), false),
#[allow(deprecated)]
AccountMeta::new_readonly(fees::id(), false),
AccountMeta::new_readonly(epoch_rewards::id(), false),
],
)],
Some(&payer.pubkey()),