Add epoch_rewards syscalls (#32159)
Co-authored-by: HaoranYi <haoran.yi@solana.com>
This commit is contained in:
parent
6f72258e3e
commit
b12180b863
|
@ -15,7 +15,9 @@ use {
|
||||||
slot_hashes::SlotHashes,
|
slot_hashes::SlotHashes,
|
||||||
slot_history::{self, SlotHistory},
|
slot_history::{self, SlotHistory},
|
||||||
stake_history::{StakeHistory, StakeHistoryEntry},
|
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;
|
let last_restart_slot = last_restart_slot.last_restart_slot;
|
||||||
SysvarAccountType::LastRestartSlot(UiLastRestartSlot { last_restart_slot })
|
SysvarAccountType::LastRestartSlot(UiLastRestartSlot { last_restart_slot })
|
||||||
})
|
})
|
||||||
|
} else if pubkey == &sysvar::epoch_rewards::id() {
|
||||||
|
deserialize::<EpochRewards>(data)
|
||||||
|
.ok()
|
||||||
|
.map(SysvarAccountType::EpochRewards)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -113,6 +119,7 @@ pub enum SysvarAccountType {
|
||||||
SlotHistory(UiSlotHistory),
|
SlotHistory(UiSlotHistory),
|
||||||
StakeHistory(Vec<UiStakeHistoryEntry>),
|
StakeHistory(Vec<UiStakeHistoryEntry>),
|
||||||
LastRestartSlot(UiLastRestartSlot),
|
LastRestartSlot(UiLastRestartSlot),
|
||||||
|
EpochRewards(EpochRewards),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Default)]
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Default)]
|
||||||
|
@ -363,5 +370,16 @@ mod test {
|
||||||
last_restart_slot: 1282
|
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),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@ pub use self::{
|
||||||
},
|
},
|
||||||
mem_ops::{SyscallMemcmp, SyscallMemcpy, SyscallMemmove, SyscallMemset},
|
mem_ops::{SyscallMemcmp, SyscallMemcpy, SyscallMemmove, SyscallMemset},
|
||||||
sysvar::{
|
sysvar::{
|
||||||
SyscallGetClockSysvar, SyscallGetEpochScheduleSysvar, SyscallGetFeesSysvar,
|
SyscallGetClockSysvar, SyscallGetEpochRewardsSysvar, SyscallGetEpochScheduleSysvar,
|
||||||
SyscallGetLastRestartSlotSysvar, SyscallGetRentSysvar,
|
SyscallGetFeesSysvar, SyscallGetLastRestartSlotSysvar, SyscallGetRentSysvar,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
|
@ -36,7 +36,7 @@ use {
|
||||||
self, blake3_syscall_enabled, curve25519_syscall_enabled,
|
self, blake3_syscall_enabled, curve25519_syscall_enabled,
|
||||||
disable_cpi_setting_executable_and_rent_epoch, disable_deploy_of_alloc_free_syscall,
|
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,
|
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,
|
error_on_syscall_bpf_function_hash_collisions, last_restart_slot_sysvar,
|
||||||
libsecp256k1_0_5_upgrade_enabled, reject_callx_r10,
|
libsecp256k1_0_5_upgrade_enabled, reject_callx_r10,
|
||||||
stop_sibling_instruction_search_at_parent, stop_truncating_strings_in_syscalls,
|
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 blake3_syscall_enabled = feature_set.is_active(&blake3_syscall_enabled::id());
|
||||||
let curve25519_syscall_enabled = feature_set.is_active(&curve25519_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 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
|
let disable_deploy_of_alloc_free_syscall = reject_deployment_of_broken_elfs
|
||||||
&& feature_set.is_active(&disable_deploy_of_alloc_free_syscall::id());
|
&& 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());
|
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,
|
SyscallGetLastRestartSlotSysvar::call,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
register_feature_gated_function!(
|
||||||
|
result,
|
||||||
|
epoch_rewards_syscall_enabled,
|
||||||
|
b"sol_get_epoch_rewrds_sysvar",
|
||||||
|
SyscallGetEpochRewardsSysvar::call,
|
||||||
|
)?;
|
||||||
|
|
||||||
// Memory ops
|
// Memory ops
|
||||||
result.register_function(b"sol_memcpy_", SyscallMemcpy::call)?;
|
result.register_function(b"sol_memcpy_", SyscallMemcpy::call)?;
|
||||||
result.register_function(b"sol_memmove_", SyscallMemmove::call)?;
|
result.register_function(b"sol_memmove_", SyscallMemmove::call)?;
|
||||||
|
@ -1807,7 +1816,9 @@ mod tests {
|
||||||
instruction::Instruction,
|
instruction::Instruction,
|
||||||
program::check_type_assumptions,
|
program::check_type_assumptions,
|
||||||
stable_layout::stable_instruction::StableInstruction,
|
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},
|
std::{mem, str::FromStr},
|
||||||
};
|
};
|
||||||
|
@ -3177,11 +3188,17 @@ mod tests {
|
||||||
src_rent.exemption_threshold = 2.0;
|
src_rent.exemption_threshold = 2.0;
|
||||||
src_rent.burn_percent = 3;
|
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();
|
let mut sysvar_cache = SysvarCache::default();
|
||||||
sysvar_cache.set_clock(src_clock.clone());
|
sysvar_cache.set_clock(src_clock.clone());
|
||||||
sysvar_cache.set_epoch_schedule(src_epochschedule);
|
sysvar_cache.set_epoch_schedule(src_epochschedule);
|
||||||
sysvar_cache.set_fees(src_fees.clone());
|
sysvar_cache.set_fees(src_fees.clone());
|
||||||
sysvar_cache.set_rent(src_rent);
|
sysvar_cache.set_rent(src_rent);
|
||||||
|
sysvar_cache.set_epoch_rewards(src_rewards);
|
||||||
|
|
||||||
let transaction_accounts = vec![
|
let transaction_accounts = vec![
|
||||||
(
|
(
|
||||||
|
@ -3200,6 +3217,10 @@ mod tests {
|
||||||
sysvar::rent::id(),
|
sysvar::rent::id(),
|
||||||
create_account_shared_data_for_test(&src_rent),
|
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);
|
with_mock_invoke_context!(invoke_context, transaction_context, transaction_accounts);
|
||||||
|
|
||||||
|
@ -3345,6 +3366,42 @@ mod tests {
|
||||||
clean_rent.burn_percent = src_rent.burn_percent;
|
clean_rent.burn_percent = src_rent.burn_percent;
|
||||||
assert!(are_bytes_equal(&got_rent, &clean_rent));
|
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>(
|
fn call_program_address_common<'a, 'b: 'a>(
|
||||||
|
|
|
@ -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!(
|
declare_syscall!(
|
||||||
/// Get a Fees sysvar
|
/// Get a Fees sysvar
|
||||||
SyscallGetFeesSysvar,
|
SyscallGetFeesSysvar,
|
||||||
|
|
|
@ -13,8 +13,9 @@ use solana_program::{
|
||||||
program_error::ProgramError,
|
program_error::ProgramError,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
sysvar::{
|
sysvar::{
|
||||||
self, clock::Clock, epoch_schedule::EpochSchedule, instructions, rent::Rent,
|
self, clock::Clock, epoch_rewards::EpochRewards, epoch_schedule::EpochSchedule,
|
||||||
slot_hashes::SlotHashes, slot_history::SlotHistory, stake_history::StakeHistory, Sysvar,
|
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[8].key, false),
|
||||||
AccountMeta::new_readonly(*accounts[9].key, false),
|
AccountMeta::new_readonly(*accounts[9].key, false),
|
||||||
AccountMeta::new_readonly(*accounts[10].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);
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ use {
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
signature::Signer,
|
signature::Signer,
|
||||||
sysvar::{
|
sysvar::{
|
||||||
clock, epoch_schedule, fees, instructions, recent_blockhashes, rent, slot_hashes,
|
clock, epoch_rewards, epoch_schedule, fees, instructions, recent_blockhashes, rent,
|
||||||
slot_history, stake_history,
|
slot_hashes, slot_history, stake_history,
|
||||||
},
|
},
|
||||||
transaction::Transaction,
|
transaction::Transaction,
|
||||||
},
|
},
|
||||||
|
@ -45,6 +45,7 @@ async fn test_sysvars() {
|
||||||
AccountMeta::new_readonly(stake_history::id(), false),
|
AccountMeta::new_readonly(stake_history::id(), false),
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
AccountMeta::new_readonly(fees::id(), false),
|
AccountMeta::new_readonly(fees::id(), false),
|
||||||
|
AccountMeta::new_readonly(epoch_rewards::id(), false),
|
||||||
],
|
],
|
||||||
)],
|
)],
|
||||||
Some(&payer.pubkey()),
|
Some(&payer.pubkey()),
|
||||||
|
@ -78,6 +79,7 @@ async fn test_sysvars() {
|
||||||
AccountMeta::new_readonly(stake_history::id(), false),
|
AccountMeta::new_readonly(stake_history::id(), false),
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
AccountMeta::new_readonly(fees::id(), false),
|
AccountMeta::new_readonly(fees::id(), false),
|
||||||
|
AccountMeta::new_readonly(epoch_rewards::id(), false),
|
||||||
],
|
],
|
||||||
)],
|
)],
|
||||||
Some(&payer.pubkey()),
|
Some(&payer.pubkey()),
|
||||||
|
|
Loading…
Reference in New Issue