Add convenience function for programs to get minimum delegation (#24175)
This commit is contained in:
parent
b4b26894cd
commit
e146e860e2
|
@ -3032,6 +3032,13 @@ dependencies = [
|
||||||
"solana-program 1.11.0",
|
"solana-program 1.11.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "solana-bpf-rust-get-minimum-delegation"
|
||||||
|
version = "1.11.0"
|
||||||
|
dependencies = [
|
||||||
|
"solana-program 1.11.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "solana-bpf-rust-instruction-introspection"
|
name = "solana-bpf-rust-instruction-introspection"
|
||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
|
|
|
@ -57,6 +57,7 @@ members = [
|
||||||
"rust/error_handling",
|
"rust/error_handling",
|
||||||
"rust/log_data",
|
"rust/log_data",
|
||||||
"rust/external_spend",
|
"rust/external_spend",
|
||||||
|
"rust/get_minimum_delegation",
|
||||||
"rust/finalize",
|
"rust/finalize",
|
||||||
"rust/instruction_introspection",
|
"rust/instruction_introspection",
|
||||||
"rust/invoke",
|
"rust/invoke",
|
||||||
|
|
|
@ -70,6 +70,7 @@ fn main() {
|
||||||
"log_data",
|
"log_data",
|
||||||
"external_spend",
|
"external_spend",
|
||||||
"finalize",
|
"finalize",
|
||||||
|
"get_minimum_delegation",
|
||||||
"instruction_introspection",
|
"instruction_introspection",
|
||||||
"invoke",
|
"invoke",
|
||||||
"invoke_and_error",
|
"invoke_and_error",
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
[package]
|
||||||
|
name = "solana-bpf-rust-get-minimum-delegation"
|
||||||
|
version = "1.11.0"
|
||||||
|
description = "Solana BPF test program written in Rust"
|
||||||
|
authors = ["Solana Maintainers <maintainers@solana.foundation>"]
|
||||||
|
repository = "https://github.com/solana-labs/solana"
|
||||||
|
license = "Apache-2.0"
|
||||||
|
homepage = "https://solana.com/"
|
||||||
|
documentation = "https://docs.rs/solana-bpf-rust-get-minimum-delegation"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
solana-program = { path = "../../../../sdk/program", version = "=1.11.0" }
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
|
[package.metadata.docs.rs]
|
||||||
|
targets = ["x86_64-unknown-linux-gnu"]
|
|
@ -0,0 +1,23 @@
|
||||||
|
//! Example/test program to get the minimum stake delegation via the helper function
|
||||||
|
|
||||||
|
#![allow(unreachable_code)]
|
||||||
|
|
||||||
|
extern crate solana_program;
|
||||||
|
use solana_program::{
|
||||||
|
account_info::AccountInfo, entrypoint::ProgramResult, msg, pubkey::Pubkey, stake,
|
||||||
|
};
|
||||||
|
|
||||||
|
solana_program::entrypoint!(process_instruction);
|
||||||
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
|
fn process_instruction(
|
||||||
|
_program_id: &Pubkey,
|
||||||
|
_accounts: &[AccountInfo],
|
||||||
|
_instruction_data: &[u8],
|
||||||
|
) -> ProgramResult {
|
||||||
|
let minimum_delegation = stake::tools::get_minimum_delegation()?;
|
||||||
|
msg!(
|
||||||
|
"The minimum stake delegation is {} lamports",
|
||||||
|
minimum_delegation
|
||||||
|
);
|
||||||
|
Ok(())
|
||||||
|
}
|
|
@ -56,6 +56,7 @@ use {
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
rent::Rent,
|
rent::Rent,
|
||||||
signature::{keypair_from_seed, Keypair, Signer},
|
signature::{keypair_from_seed, Keypair, Signer},
|
||||||
|
stake,
|
||||||
system_instruction::{self, MAX_PERMITTED_DATA_LENGTH},
|
system_instruction::{self, MAX_PERMITTED_DATA_LENGTH},
|
||||||
system_program,
|
system_program,
|
||||||
sysvar::{self, clock, rent},
|
sysvar::{self, clock, rent},
|
||||||
|
@ -3522,3 +3523,32 @@ fn test_program_fees() {
|
||||||
let post_balance = bank_client.get_balance(&mint_keypair.pubkey()).unwrap();
|
let post_balance = bank_client.get_balance(&mint_keypair.pubkey()).unwrap();
|
||||||
assert_eq!(pre_balance - post_balance, expected_min_fee);
|
assert_eq!(pre_balance - post_balance, expected_min_fee);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[cfg(feature = "bpf_rust")]
|
||||||
|
fn test_get_minimum_delegation() {
|
||||||
|
let GenesisConfigInfo {
|
||||||
|
genesis_config,
|
||||||
|
mint_keypair,
|
||||||
|
..
|
||||||
|
} = create_genesis_config(100_123_456_789);
|
||||||
|
let mut bank = Bank::new_for_tests(&genesis_config);
|
||||||
|
bank.feature_set = Arc::new(FeatureSet::all_enabled());
|
||||||
|
|
||||||
|
let (name, id, entrypoint) = solana_bpf_loader_program!();
|
||||||
|
bank.add_builtin(&name, &id, entrypoint);
|
||||||
|
let bank = Arc::new(bank);
|
||||||
|
let bank_client = BankClient::new_shared(&bank);
|
||||||
|
|
||||||
|
let program_id = load_bpf_program(
|
||||||
|
&bank_client,
|
||||||
|
&bpf_loader::id(),
|
||||||
|
&mint_keypair,
|
||||||
|
"solana_bpf_rust_get_minimum_delegation",
|
||||||
|
);
|
||||||
|
|
||||||
|
let account_metas = vec![AccountMeta::new_readonly(stake::program::id(), false)];
|
||||||
|
let instruction = Instruction::new_with_bytes(program_id, &[], account_metas);
|
||||||
|
let result = bank_client.send_and_confirm_instruction(&mint_keypair, instruction);
|
||||||
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
|
|
|
@ -228,8 +228,11 @@ pub enum StakeInstruction {
|
||||||
/// # Account references
|
/// # Account references
|
||||||
/// None
|
/// None
|
||||||
///
|
///
|
||||||
/// The minimum delegation will be returned via the transaction context's returndata.
|
/// Returns the minimum delegation as a little-endian encoded u64 value.
|
||||||
/// Use `get_return_data()` to retrieve the result.
|
/// Programs can use the [`get_minimum_delegation()`] helper function to invoke and
|
||||||
|
/// retrieve the return value for this instruction.
|
||||||
|
///
|
||||||
|
/// [`get_minimum_delegation()`]: super::tools::get_minimum_delegation
|
||||||
GetMinimumDelegation,
|
GetMinimumDelegation,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
pub mod config;
|
pub mod config;
|
||||||
pub mod instruction;
|
pub mod instruction;
|
||||||
pub mod state;
|
pub mod state;
|
||||||
|
pub mod tools;
|
||||||
|
|
||||||
pub mod program {
|
pub mod program {
|
||||||
crate::declare_id!("Stake11111111111111111111111111111111111111");
|
crate::declare_id!("Stake11111111111111111111111111111111111111");
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
//! Utility functions
|
||||||
|
use crate::program_error::ProgramError;
|
||||||
|
|
||||||
|
/// Helper function for programs to call [`GetMinimumDelegation`] and then fetch the return data
|
||||||
|
///
|
||||||
|
/// This fn handles performing the CPI to call the [`GetMinimumDelegation`] function, and then
|
||||||
|
/// calls [`get_return_data()`] to fetch the return data.
|
||||||
|
///
|
||||||
|
/// [`GetMinimumDelegation`]: super::instruction::StakeInstruction::GetMinimumDelegation
|
||||||
|
/// [`get_return_data()`]: crate::program::get_return_data
|
||||||
|
pub fn get_minimum_delegation() -> Result<u64, ProgramError> {
|
||||||
|
let instruction = super::instruction::get_minimum_delegation();
|
||||||
|
crate::program::invoke_unchecked(&instruction, &[])?;
|
||||||
|
get_minimum_delegation_return_data()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper function for programs to get the return data after calling [`GetMinimumDelegation`]
|
||||||
|
///
|
||||||
|
/// This fn handles calling [`get_return_data()`], ensures the result is from the correct
|
||||||
|
/// program, and returns the correct type.
|
||||||
|
///
|
||||||
|
/// [`GetMinimumDelegation`]: super::instruction::StakeInstruction::GetMinimumDelegation
|
||||||
|
/// [`get_return_data()`]: crate::program::get_return_data
|
||||||
|
fn get_minimum_delegation_return_data() -> Result<u64, ProgramError> {
|
||||||
|
crate::program::get_return_data()
|
||||||
|
.ok_or(ProgramError::InvalidInstructionData)
|
||||||
|
.and_then(|(program_id, return_data)| {
|
||||||
|
(program_id == super::program::id())
|
||||||
|
.then(|| return_data)
|
||||||
|
.ok_or(ProgramError::IncorrectProgramId)
|
||||||
|
})
|
||||||
|
.and_then(|return_data| {
|
||||||
|
return_data
|
||||||
|
.try_into()
|
||||||
|
.or(Err(ProgramError::InvalidInstructionData))
|
||||||
|
})
|
||||||
|
.map(u64::from_le_bytes)
|
||||||
|
}
|
Loading…
Reference in New Issue