sdk, programs/bpf_loader: add sol_remaining_compute_units syscall (#31640)
bpf_loader: add sol_remaining_compute_units syscall Co-authored-by: jonch <9093549+jon-chuang@users.noreply.github.com>
This commit is contained in:
parent
c40e88aef9
commit
525e59f01a
|
@ -157,6 +157,9 @@ with program logs.
|
||||||
|
|
||||||
## Compute Budget
|
## Compute Budget
|
||||||
|
|
||||||
|
Use the system call `sol_remaining_compute_units()` to return a `u64` indicating
|
||||||
|
the number of compute units remaining for this transaction.
|
||||||
|
|
||||||
Use the system call
|
Use the system call
|
||||||
[`sol_log_compute_units()`](https://github.com/solana-labs/solana/blob/d3a3a7548c857f26ec2cb10e270da72d373020ec/sdk/sbf/c/inc/solana_sdk.h#L140)
|
[`sol_log_compute_units()`](https://github.com/solana-labs/solana/blob/d3a3a7548c857f26ec2cb10e270da72d373020ec/sdk/sbf/c/inc/solana_sdk.h#L140)
|
||||||
to log a message containing the remaining number of compute units the program
|
to log a message containing the remaining number of compute units the program
|
||||||
|
|
|
@ -355,6 +355,9 @@ fn custom_panic(info: &core::panic::PanicInfo<'_>) {
|
||||||
|
|
||||||
## Compute Budget
|
## Compute Budget
|
||||||
|
|
||||||
|
Use the system call `sol_remaining_compute_units()` to return a `u64` indicating
|
||||||
|
the number of compute units remaining for this transaction.
|
||||||
|
|
||||||
Use the system call
|
Use the system call
|
||||||
[`sol_log_compute_units()`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/log.rs#L141)
|
[`sol_log_compute_units()`](https://github.com/solana-labs/solana/blob/d9b0fc0e3eec67dfe4a97d9298b15969b2804fab/sdk/program/src/log.rs#L141)
|
||||||
to log a message containing the remaining number of compute units the program
|
to log a message containing the remaining number of compute units the program
|
||||||
|
|
|
@ -130,6 +130,8 @@ pub struct ComputeBudget {
|
||||||
/// of compute units consumed to call poseidon syscall for a given number
|
/// of compute units consumed to call poseidon syscall for a given number
|
||||||
/// of inputs.
|
/// of inputs.
|
||||||
pub poseidon_cost_coefficient_c: u64,
|
pub poseidon_cost_coefficient_c: u64,
|
||||||
|
/// Number of compute units consumed for accessing the remaining compute units.
|
||||||
|
pub get_remaining_compute_units_cost: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for ComputeBudget {
|
impl Default for ComputeBudget {
|
||||||
|
@ -181,6 +183,7 @@ impl ComputeBudget {
|
||||||
loaded_accounts_data_size_limit: MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES,
|
loaded_accounts_data_size_limit: MAX_LOADED_ACCOUNTS_DATA_SIZE_BYTES,
|
||||||
poseidon_cost_coefficient_a: 61,
|
poseidon_cost_coefficient_a: 61,
|
||||||
poseidon_cost_coefficient_c: 542,
|
poseidon_cost_coefficient_c: 542,
|
||||||
|
get_remaining_compute_units_cost: 100,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,8 +40,8 @@ use {
|
||||||
enable_early_verification_of_account_modifications, enable_partitioned_epoch_reward,
|
enable_early_verification_of_account_modifications, enable_partitioned_epoch_reward,
|
||||||
enable_poseidon_syscall, error_on_syscall_bpf_function_hash_collisions,
|
enable_poseidon_syscall, error_on_syscall_bpf_function_hash_collisions,
|
||||||
last_restart_slot_sysvar, libsecp256k1_0_5_upgrade_enabled, reject_callx_r10,
|
last_restart_slot_sysvar, libsecp256k1_0_5_upgrade_enabled, reject_callx_r10,
|
||||||
stop_sibling_instruction_search_at_parent, stop_truncating_strings_in_syscalls,
|
remaining_compute_units_syscall_enabled, stop_sibling_instruction_search_at_parent,
|
||||||
switch_to_new_elf_parser,
|
stop_truncating_strings_in_syscalls, switch_to_new_elf_parser,
|
||||||
},
|
},
|
||||||
hash::{Hasher, HASH_BYTES},
|
hash::{Hasher, HASH_BYTES},
|
||||||
instruction::{
|
instruction::{
|
||||||
|
@ -164,6 +164,8 @@ pub fn create_program_runtime_environment_v1<'a>(
|
||||||
&& 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());
|
||||||
let enable_poseidon_syscall = feature_set.is_active(&enable_poseidon_syscall::id());
|
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());
|
||||||
// !!! ATTENTION !!!
|
// !!! ATTENTION !!!
|
||||||
// When adding new features for RBPF here,
|
// When adding new features for RBPF here,
|
||||||
// also add them to `Bank::apply_builtin_program_feature_transitions()`.
|
// also add them to `Bank::apply_builtin_program_feature_transitions()`.
|
||||||
|
@ -335,6 +337,14 @@ pub fn create_program_runtime_environment_v1<'a>(
|
||||||
SyscallPoseidon::call,
|
SyscallPoseidon::call,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
// Accessing remaining compute units
|
||||||
|
register_feature_gated_function!(
|
||||||
|
result,
|
||||||
|
remaining_compute_units_syscall_enabled,
|
||||||
|
*b"sol_remaining_compute_units",
|
||||||
|
SyscallRemainingComputeUnits::call
|
||||||
|
)?;
|
||||||
|
|
||||||
// Log data
|
// Log data
|
||||||
result.register_function_hashed(*b"sol_log_data", SyscallLogData::call)?;
|
result.register_function_hashed(*b"sol_log_data", SyscallLogData::call)?;
|
||||||
|
|
||||||
|
@ -1877,6 +1887,26 @@ declare_syscall!(
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
declare_syscall!(
|
||||||
|
/// Read remaining compute units
|
||||||
|
SyscallRemainingComputeUnits,
|
||||||
|
fn inner_call(
|
||||||
|
invoke_context: &mut InvokeContext,
|
||||||
|
_arg1: u64,
|
||||||
|
_arg2: u64,
|
||||||
|
_arg3: u64,
|
||||||
|
_arg4: u64,
|
||||||
|
_arg5: u64,
|
||||||
|
_memory_mapping: &mut MemoryMapping,
|
||||||
|
) -> Result<u64, Error> {
|
||||||
|
let budget = invoke_context.get_compute_budget();
|
||||||
|
consume_compute_meter(invoke_context, budget.syscall_base_cost)?;
|
||||||
|
|
||||||
|
use solana_rbpf::vm::ContextObject;
|
||||||
|
Ok(invoke_context.get_remaining())
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[allow(clippy::arithmetic_side_effects)]
|
#[allow(clippy::arithmetic_side_effects)]
|
||||||
#[allow(clippy::indexing_slicing)]
|
#[allow(clippy::indexing_slicing)]
|
||||||
|
|
|
@ -5889,6 +5889,16 @@ dependencies = [
|
||||||
"solana-sbf-rust-realloc",
|
"solana-sbf-rust-realloc",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "solana-sbf-rust-remaining-compute-units"
|
||||||
|
version = "1.17.0"
|
||||||
|
dependencies = [
|
||||||
|
"solana-program",
|
||||||
|
"solana-program-runtime",
|
||||||
|
"solana-program-test",
|
||||||
|
"solana-sdk",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "solana-sbf-rust-ro-account_modify"
|
name = "solana-sbf-rust-ro-account_modify"
|
||||||
version = "1.17.0"
|
version = "1.17.0"
|
||||||
|
|
|
@ -145,6 +145,7 @@ members = [
|
||||||
"rust/rand",
|
"rust/rand",
|
||||||
"rust/realloc",
|
"rust/realloc",
|
||||||
"rust/realloc_invoke",
|
"rust/realloc_invoke",
|
||||||
|
"rust/remaining_compute_units",
|
||||||
"rust/ro_account_modify",
|
"rust/ro_account_modify",
|
||||||
"rust/ro_modify",
|
"rust/ro_modify",
|
||||||
"rust/sanity",
|
"rust/sanity",
|
||||||
|
|
|
@ -96,6 +96,7 @@ fn main() {
|
||||||
"rand",
|
"rand",
|
||||||
"realloc",
|
"realloc",
|
||||||
"realloc_invoke",
|
"realloc_invoke",
|
||||||
|
"remaining_compute_units",
|
||||||
"ro_modify",
|
"ro_modify",
|
||||||
"ro_account_modify",
|
"ro_account_modify",
|
||||||
"sanity",
|
"sanity",
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/**
|
||||||
|
* @brief sol_remaining_compute_units Syscall test
|
||||||
|
*/
|
||||||
|
#include <solana_sdk.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
extern uint64_t entrypoint(const uint8_t *input) {
|
||||||
|
char buffer[200];
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (; i < 100000; ++i) {
|
||||||
|
if (i % 500 == 0) {
|
||||||
|
uint64_t remaining = sol_remaining_compute_units();
|
||||||
|
snprintf(buffer, 200, "remaining compute units: %d", (int)remaining);
|
||||||
|
sol_log(buffer);
|
||||||
|
if (remaining < 25000) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
[package]
|
||||||
|
name = "solana-sbf-rust-remaining-compute-units"
|
||||||
|
documentation = "https://docs.rs/solana-sbf-rust-remaining-compute-units"
|
||||||
|
version = { workspace = true }
|
||||||
|
description = { workspace = true }
|
||||||
|
authors = { workspace = true }
|
||||||
|
repository = { workspace = true }
|
||||||
|
homepage = { workspace = true }
|
||||||
|
license = { workspace = true }
|
||||||
|
edition = { workspace = true }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
no-entrypoint = []
|
||||||
|
test-bpf = []
|
||||||
|
dummy-for-ci-check = ["test-bpf"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
solana-program = { workspace = true }
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
solana-program-runtime = { workspace = true }
|
||||||
|
solana-program-test = { workspace = true }
|
||||||
|
solana-sdk = { workspace = true }
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib", "lib"]
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
targets = ["x86_64-unknown-linux-gnu"]
|
|
@ -0,0 +1,29 @@
|
||||||
|
//! @brief Example Rust-based BPF program that exercises the sol_remaining_compute_units syscall
|
||||||
|
|
||||||
|
extern crate solana_program;
|
||||||
|
use solana_program::{
|
||||||
|
account_info::AccountInfo, compute_units::sol_remaining_compute_units,
|
||||||
|
entrypoint::ProgramResult, msg, pubkey::Pubkey,
|
||||||
|
};
|
||||||
|
solana_program::entrypoint!(process_instruction);
|
||||||
|
pub fn process_instruction(
|
||||||
|
_program_id: &Pubkey,
|
||||||
|
_accounts: &[AccountInfo],
|
||||||
|
_instruction_data: &[u8],
|
||||||
|
) -> ProgramResult {
|
||||||
|
let mut i = 0u32;
|
||||||
|
for _ in 0..100_000 {
|
||||||
|
if i % 500 == 0 {
|
||||||
|
let remaining = sol_remaining_compute_units();
|
||||||
|
msg!("remaining compute units: {:?}", remaining);
|
||||||
|
if remaining < 25_000 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i = i.saturating_add(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg!("i: {:?}", i);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#![cfg(feature = "test-bpf")]
|
||||||
|
|
||||||
|
use {
|
||||||
|
solana_program_test::*,
|
||||||
|
solana_sbf_rust_remaining_compute_units::process_instruction,
|
||||||
|
solana_sdk::{
|
||||||
|
instruction::Instruction, pubkey::Pubkey, signature::Signer, transaction::Transaction,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_remaining_compute_units() {
|
||||||
|
let program_id = Pubkey::new_unique();
|
||||||
|
let program_test = ProgramTest::new(
|
||||||
|
"solana_sbf_rust_remaining_compute_units",
|
||||||
|
program_id,
|
||||||
|
processor!(process_instruction),
|
||||||
|
);
|
||||||
|
let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
|
||||||
|
|
||||||
|
let mut transaction = Transaction::new_with_payer(
|
||||||
|
&[Instruction::new_with_bincode(program_id, &(), vec![])],
|
||||||
|
Some(&payer.pubkey()),
|
||||||
|
);
|
||||||
|
transaction.sign(&[&payer], recent_blockhash);
|
||||||
|
banks_client.process_transaction(transaction).await.unwrap();
|
||||||
|
}
|
|
@ -8111,6 +8111,7 @@ impl Bank {
|
||||||
feature_set::disable_deploy_of_alloc_free_syscall::id(),
|
feature_set::disable_deploy_of_alloc_free_syscall::id(),
|
||||||
feature_set::last_restart_slot_sysvar::id(),
|
feature_set::last_restart_slot_sysvar::id(),
|
||||||
feature_set::delay_visibility_of_program_deployment::id(),
|
feature_set::delay_visibility_of_program_deployment::id(),
|
||||||
|
feature_set::remaining_compute_units_syscall_enabled::id(),
|
||||||
];
|
];
|
||||||
if !only_apply_transitions_for_new_features
|
if !only_apply_transitions_for_new_features
|
||||||
|| FEATURES_AFFECTING_RBPF
|
|| FEATURES_AFFECTING_RBPF
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
/// Return the remaining compute units the program may consume
|
||||||
|
#[inline]
|
||||||
|
pub fn sol_remaining_compute_units() -> u64 {
|
||||||
|
#[cfg(target_os = "solana")]
|
||||||
|
unsafe {
|
||||||
|
crate::syscalls::sol_remaining_compute_units()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "solana"))]
|
||||||
|
{
|
||||||
|
crate::program_stubs::sol_remaining_compute_units()
|
||||||
|
}
|
||||||
|
}
|
|
@ -483,6 +483,7 @@ pub mod bpf_loader;
|
||||||
pub mod bpf_loader_deprecated;
|
pub mod bpf_loader_deprecated;
|
||||||
pub mod bpf_loader_upgradeable;
|
pub mod bpf_loader_upgradeable;
|
||||||
pub mod clock;
|
pub mod clock;
|
||||||
|
pub mod compute_units;
|
||||||
pub mod debug_account_data;
|
pub mod debug_account_data;
|
||||||
pub mod decode_error;
|
pub mod decode_error;
|
||||||
pub mod ed25519_program;
|
pub mod ed25519_program;
|
||||||
|
|
|
@ -30,6 +30,10 @@ pub trait SyscallStubs: Sync + Send {
|
||||||
fn sol_log_compute_units(&self) {
|
fn sol_log_compute_units(&self) {
|
||||||
sol_log("SyscallStubs: sol_log_compute_units() not available");
|
sol_log("SyscallStubs: sol_log_compute_units() not available");
|
||||||
}
|
}
|
||||||
|
fn sol_remaining_compute_units(&self) -> u64 {
|
||||||
|
sol_log("SyscallStubs: sol_remaining_compute_units() defaulting to 0");
|
||||||
|
0
|
||||||
|
}
|
||||||
fn sol_invoke_signed(
|
fn sol_invoke_signed(
|
||||||
&self,
|
&self,
|
||||||
_instruction: &Instruction,
|
_instruction: &Instruction,
|
||||||
|
@ -126,6 +130,10 @@ pub(crate) fn sol_log_compute_units() {
|
||||||
SYSCALL_STUBS.read().unwrap().sol_log_compute_units();
|
SYSCALL_STUBS.read().unwrap().sol_log_compute_units();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) fn sol_remaining_compute_units() -> u64 {
|
||||||
|
SYSCALL_STUBS.read().unwrap().sol_remaining_compute_units()
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) fn sol_invoke_signed(
|
pub(crate) fn sol_invoke_signed(
|
||||||
instruction: &Instruction,
|
instruction: &Instruction,
|
||||||
account_infos: &[AccountInfo],
|
account_infos: &[AccountInfo],
|
||||||
|
|
|
@ -70,6 +70,7 @@ define_syscall!(fn sol_alt_bn128_group_op(group_op: u64, input: *const u8, input
|
||||||
define_syscall!(fn sol_big_mod_exp(params: *const u8, result: *mut u8) -> u64);
|
define_syscall!(fn sol_big_mod_exp(params: *const u8, result: *mut u8) -> u64);
|
||||||
define_syscall!(fn sol_get_epoch_rewards_sysvar(addr: *mut u8) -> u64);
|
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_poseidon(parameters: u64, endianness: u64, vals: *const u8, val_len: u64, hash_result: *mut u8) -> u64);
|
||||||
|
define_syscall!(fn sol_remaining_compute_units() -> u64);
|
||||||
|
|
||||||
#[cfg(target_feature = "static-syscalls")]
|
#[cfg(target_feature = "static-syscalls")]
|
||||||
pub const fn sys_hash(name: &str) -> usize {
|
pub const fn sys_hash(name: &str) -> usize {
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
#pragma once
|
||||||
|
/**
|
||||||
|
* @brief Solana logging utilities
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sol/types.h>
|
||||||
|
#include <sol/string.h>
|
||||||
|
#include <sol/entrypoint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints a string to stdout
|
||||||
|
*/
|
||||||
|
/* DO NOT MODIFY THIS GENERATED FILE. INSTEAD CHANGE sdk/sbf/c/inc/sol/inc/compute_units.inc AND RUN `cargo run --bin gen-headers` */
|
||||||
|
#ifndef SOL_SBFV2
|
||||||
|
uint64_t sol_remaining_compute_units();
|
||||||
|
#else
|
||||||
|
typedef uint64_t(*sol_remaining_compute_units_pointer_type)();
|
||||||
|
static uint64_t sol_remaining_compute_units() {
|
||||||
|
sol_remaining_compute_units_pointer_type sol_remaining_compute_units_pointer = (sol_remaining_compute_units_pointer_type) 3991886574;
|
||||||
|
return sol_remaining_compute_units_pointer();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SOL_TEST
|
||||||
|
/**
|
||||||
|
* Stub functions when building tests
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint64_t sol_remaining_compute_units() {
|
||||||
|
return UINT64_MAX;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**@}*/
|
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
/**
|
||||||
|
* @brief Solana logging utilities
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sol/types.h>
|
||||||
|
#include <sol/string.h>
|
||||||
|
#include <sol/entrypoint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prints a string to stdout
|
||||||
|
*/
|
||||||
|
@SYSCALL uint64_t sol_remaining_compute_units();
|
||||||
|
|
||||||
|
#ifdef SOL_TEST
|
||||||
|
/**
|
||||||
|
* Stub functions when building tests
|
||||||
|
*/
|
||||||
|
|
||||||
|
uint64_t sol_remaining_compute_units() {
|
||||||
|
return UINT64_MAX;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**@}*/
|
|
@ -6,6 +6,7 @@
|
||||||
#include <sol/assert.h>
|
#include <sol/assert.h>
|
||||||
#include <sol/big_mod_exp.h>
|
#include <sol/big_mod_exp.h>
|
||||||
#include <sol/blake3.h>
|
#include <sol/blake3.h>
|
||||||
|
#include <sol/compute_units.h>
|
||||||
#include <sol/cpi.h>
|
#include <sol/cpi.h>
|
||||||
#include <sol/deserialize.h>
|
#include <sol/deserialize.h>
|
||||||
#include <sol/deserialize_deprecated.h>
|
#include <sol/deserialize_deprecated.h>
|
||||||
|
|
|
@ -691,6 +691,10 @@ pub mod timely_vote_credits {
|
||||||
solana_sdk::declare_id!("2oXpeh141pPZCTCFHBsvCwG2BtaHZZAtrVhwaxSy6brS");
|
solana_sdk::declare_id!("2oXpeh141pPZCTCFHBsvCwG2BtaHZZAtrVhwaxSy6brS");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub mod remaining_compute_units_syscall_enabled {
|
||||||
|
solana_sdk::declare_id!("5TuppMutoyzhUSfuYdhgzD47F92GL1g89KpCZQKqedxP");
|
||||||
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
/// Map of feature identifiers to user-visible description
|
/// Map of feature identifiers to user-visible description
|
||||||
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
||||||
|
@ -856,6 +860,7 @@ lazy_static! {
|
||||||
(revise_turbine_epoch_stakes::id(), "revise turbine epoch stakes"),
|
(revise_turbine_epoch_stakes::id(), "revise turbine epoch stakes"),
|
||||||
(enable_poseidon_syscall::id(), "Enable Poseidon syscall"),
|
(enable_poseidon_syscall::id(), "Enable Poseidon syscall"),
|
||||||
(timely_vote_credits::id(), "use timeliness of votes in determining credits to award"),
|
(timely_vote_credits::id(), "use timeliness of votes in determining credits to award"),
|
||||||
|
(remaining_compute_units_syscall_enabled::id(), "enable the remaining_compute_units syscall"),
|
||||||
/*************** ADD NEW FEATURES HERE ***************/
|
/*************** ADD NEW FEATURES HERE ***************/
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
|
|
Loading…
Reference in New Issue