add stake_api config account (#5531)
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3725,6 +3725,7 @@ dependencies = [
|
|||||||
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"solana-config-api 0.18.0-pre1",
|
||||||
"solana-logger 0.18.0-pre1",
|
"solana-logger 0.18.0-pre1",
|
||||||
"solana-metrics 0.18.0-pre1",
|
"solana-metrics 0.18.0-pre1",
|
||||||
"solana-sdk 0.18.0-pre1",
|
"solana-sdk 0.18.0-pre1",
|
||||||
|
@ -331,9 +331,9 @@ fn main() -> Result<(), Box<dyn error::Error>> {
|
|||||||
builder = append_primordial_accounts(file, AccountFileFormat::Keypair, builder)?;
|
builder = append_primordial_accounts(file, AccountFileFormat::Keypair, builder)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// add the reward pools
|
// add genesis stuff from storage and stake
|
||||||
builder = solana_storage_api::rewards_pools::genesis(builder);
|
builder = solana_storage_api::rewards_pools::genesis(builder);
|
||||||
builder = solana_stake_api::rewards_pools::genesis(builder);
|
builder = solana_stake_api::genesis(builder);
|
||||||
|
|
||||||
create_new_ledger(&ledger_path, &builder.build())?;
|
create_new_ledger(&ledger_path, &builder.build())?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -18,6 +18,7 @@ solana-logger = { path = "../../logger", version = "0.18.0-pre1" }
|
|||||||
solana-metrics = { path = "../../metrics", version = "0.18.0-pre1" }
|
solana-metrics = { path = "../../metrics", version = "0.18.0-pre1" }
|
||||||
solana-sdk = { path = "../../sdk", version = "0.18.0-pre1" }
|
solana-sdk = { path = "../../sdk", version = "0.18.0-pre1" }
|
||||||
solana-vote-api = { path = "../vote_api", version = "0.18.0-pre1" }
|
solana-vote-api = { path = "../vote_api", version = "0.18.0-pre1" }
|
||||||
|
solana-config-api = { path = "../config_api", version = "0.18.0-pre1" }
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
crate-type = ["lib"]
|
crate-type = ["lib"]
|
||||||
|
89
programs/stake_api/src/config.rs
Normal file
89
programs/stake_api/src/config.rs
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
//! config for staking
|
||||||
|
//! carries variables that the stake program cares about
|
||||||
|
use bincode::{deserialize, serialized_size};
|
||||||
|
use serde_derive::{Deserialize, Serialize};
|
||||||
|
use solana_config_api::{create_config_account, get_config_data, ConfigState};
|
||||||
|
use solana_sdk::{
|
||||||
|
account::{Account, KeyedAccount},
|
||||||
|
instruction::InstructionError,
|
||||||
|
pubkey::Pubkey,
|
||||||
|
};
|
||||||
|
|
||||||
|
// stake config ID
|
||||||
|
const ID: [u8; 32] = [
|
||||||
|
6, 161, 216, 23, 165, 2, 5, 11, 104, 7, 145, 230, 206, 109, 184, 142, 30, 91, 113, 80, 246, 31,
|
||||||
|
198, 121, 10, 78, 180, 209, 0, 0, 0, 0,
|
||||||
|
];
|
||||||
|
|
||||||
|
solana_sdk::solana_name_id!(ID, "StakeConfig11111111111111111111111111111111");
|
||||||
|
|
||||||
|
// means that no more tha
|
||||||
|
pub const DEFAULT_WARMUP_RATE: f64 = 0.15;
|
||||||
|
pub const DEFAULT_COOLDOWN_RATE: f64 = 0.15;
|
||||||
|
pub const DEFAULT_SLASH_PENALTY: u8 = ((5 * std::u8::MAX as usize) / 100) as u8;
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Clone, Copy)]
|
||||||
|
pub struct Config {
|
||||||
|
pub warmup_rate: f64,
|
||||||
|
pub cooldown_rate: f64,
|
||||||
|
pub slash_penalty: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
pub fn from(account: &Account) -> Option<Self> {
|
||||||
|
get_config_data(&account.data)
|
||||||
|
.ok()
|
||||||
|
.and_then(|data| deserialize(data).ok())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for Config {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
warmup_rate: DEFAULT_WARMUP_RATE,
|
||||||
|
cooldown_rate: DEFAULT_COOLDOWN_RATE,
|
||||||
|
slash_penalty: DEFAULT_SLASH_PENALTY,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConfigState for Config {
|
||||||
|
fn max_space() -> u64 {
|
||||||
|
serialized_size(&Config::default()).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn genesis() -> (Pubkey, Account) {
|
||||||
|
(id(), create_config_account(vec![], &Config::default(), 100))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_account(lamports: u64, config: &Config) -> Account {
|
||||||
|
create_config_account(vec![], config, lamports)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_keyed_account(account: &KeyedAccount) -> Result<Config, InstructionError> {
|
||||||
|
if !check_id(account.unsigned_key()) {
|
||||||
|
return Err(InstructionError::InvalidArgument);
|
||||||
|
}
|
||||||
|
Config::from(account.account).ok_or(InstructionError::InvalidArgument)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test() {
|
||||||
|
let mut account = create_account(1, &Config::default());
|
||||||
|
assert_eq!(Config::from(&account), Some(Config::default()));
|
||||||
|
assert_eq!(
|
||||||
|
from_keyed_account(&KeyedAccount::new(&Pubkey::default(), false, &mut account)),
|
||||||
|
Err(InstructionError::InvalidArgument)
|
||||||
|
);
|
||||||
|
let (pubkey, mut account) = genesis();
|
||||||
|
assert_eq!(
|
||||||
|
from_keyed_account(&KeyedAccount::new(&pubkey, false, &mut account)),
|
||||||
|
Ok(Config::default())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
pub mod config;
|
||||||
pub mod rewards_pools;
|
pub mod rewards_pools;
|
||||||
pub mod stake_instruction;
|
pub mod stake_instruction;
|
||||||
pub mod stake_state;
|
pub mod stake_state;
|
||||||
@ -11,3 +12,12 @@ solana_sdk::solana_name_id!(
|
|||||||
STAKE_PROGRAM_ID,
|
STAKE_PROGRAM_ID,
|
||||||
"Stake11111111111111111111111111111111111111"
|
"Stake11111111111111111111111111111111111111"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
use solana_sdk::genesis_block::Builder;
|
||||||
|
|
||||||
|
pub fn genesis(mut builder: Builder) -> Builder {
|
||||||
|
for (pubkey, account) in crate::rewards_pools::genesis().iter() {
|
||||||
|
builder = builder.rewards_pool(*pubkey, account.clone());
|
||||||
|
}
|
||||||
|
builder.accounts(&[crate::config::genesis()])
|
||||||
|
}
|
||||||
|
@ -2,12 +2,13 @@
|
|||||||
//! * initialize genesis with rewards pools
|
//! * initialize genesis with rewards pools
|
||||||
//! * keep track of rewards
|
//! * keep track of rewards
|
||||||
//! * own mining pools
|
//! * own mining pools
|
||||||
|
use crate::stake_state::StakeState;
|
||||||
use crate::stake_state::create_rewards_pool;
|
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use solana_sdk::genesis_block::Builder;
|
use solana_sdk::{
|
||||||
use solana_sdk::hash::{hash, Hash};
|
account::Account,
|
||||||
use solana_sdk::pubkey::Pubkey;
|
hash::{hash, Hash},
|
||||||
|
pubkey::Pubkey,
|
||||||
|
};
|
||||||
|
|
||||||
// base rewards pool ID
|
// base rewards pool ID
|
||||||
const ID: [u8; 32] = [
|
const ID: [u8; 32] = [
|
||||||
@ -20,16 +21,6 @@ solana_sdk::solana_name_id!(ID, "StakeRewards1111111111111111111111111111111");
|
|||||||
// to cut down on collisions for redemptions, we make multiple accounts
|
// to cut down on collisions for redemptions, we make multiple accounts
|
||||||
pub const NUM_REWARDS_POOLS: usize = 256;
|
pub const NUM_REWARDS_POOLS: usize = 256;
|
||||||
|
|
||||||
pub fn genesis(mut builder: Builder) -> Builder {
|
|
||||||
let mut pubkey = id();
|
|
||||||
|
|
||||||
for _i in 0..NUM_REWARDS_POOLS {
|
|
||||||
builder = builder.rewards_pool(pubkey, create_rewards_pool());
|
|
||||||
pubkey = Pubkey::new(hash(pubkey.as_ref()).as_ref());
|
|
||||||
}
|
|
||||||
builder
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn random_id() -> Pubkey {
|
pub fn random_id() -> Pubkey {
|
||||||
let mut id = Hash::new(&ID);
|
let mut id = Hash::new(&ID);
|
||||||
|
|
||||||
@ -40,24 +31,31 @@ pub fn random_id() -> Pubkey {
|
|||||||
Pubkey::new(id.as_ref())
|
Pubkey::new(id.as_ref())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn genesis() -> Vec<(Pubkey, Account)> {
|
||||||
|
let mut accounts = Vec::with_capacity(NUM_REWARDS_POOLS);
|
||||||
|
let mut pubkey = id();
|
||||||
|
|
||||||
|
for _i in 0..NUM_REWARDS_POOLS {
|
||||||
|
accounts.push((
|
||||||
|
pubkey,
|
||||||
|
Account::new_data(std::u64::MAX, &StakeState::RewardsPool, &crate::id()).unwrap(),
|
||||||
|
));
|
||||||
|
pubkey = Pubkey::new(hash(pubkey.as_ref()).as_ref());
|
||||||
|
}
|
||||||
|
accounts
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use solana_sdk::genesis_block::Builder;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test() {
|
fn test() {
|
||||||
let builder = Builder::new();
|
let accounts = genesis();
|
||||||
|
|
||||||
let genesis_block = genesis(builder).build();
|
|
||||||
|
|
||||||
for _i in 0..NUM_REWARDS_POOLS {
|
for _i in 0..NUM_REWARDS_POOLS {
|
||||||
let id = random_id();
|
let id = random_id();
|
||||||
assert!(genesis_block
|
assert!(accounts.iter().position(|x| x.0 == id).is_some());
|
||||||
.rewards_pools
|
|
||||||
.iter()
|
|
||||||
.position(|x| x.0 == id)
|
|
||||||
.is_some());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
use crate::id;
|
use crate::{
|
||||||
use crate::stake_state::{StakeAccount, StakeState};
|
config, id,
|
||||||
|
stake_state::{StakeAccount, StakeState},
|
||||||
|
};
|
||||||
use bincode::deserialize;
|
use bincode::deserialize;
|
||||||
use log::*;
|
use log::*;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
@ -18,6 +20,7 @@ pub enum StakeInstruction {
|
|||||||
/// 0 - Uninitialized StakeAccount to be delegated <= must have this signature
|
/// 0 - Uninitialized StakeAccount to be delegated <= must have this signature
|
||||||
/// 1 - VoteAccount to which this Stake will be delegated
|
/// 1 - VoteAccount to which this Stake will be delegated
|
||||||
/// 2 - Clock sysvar Account that carries clock bank epoch
|
/// 2 - Clock sysvar Account that carries clock bank epoch
|
||||||
|
/// 3 - Config Account that carries stake config
|
||||||
///
|
///
|
||||||
/// The u64 is the portion of the Stake account balance to be activated,
|
/// The u64 is the portion of the Stake account balance to be activated,
|
||||||
/// must be less than StakeAccount.lamports
|
/// must be less than StakeAccount.lamports
|
||||||
@ -96,6 +99,7 @@ pub fn delegate_stake(stake_pubkey: &Pubkey, vote_pubkey: &Pubkey, stake: u64) -
|
|||||||
AccountMeta::new(*stake_pubkey, true),
|
AccountMeta::new(*stake_pubkey, true),
|
||||||
AccountMeta::new_credit_only(*vote_pubkey, false),
|
AccountMeta::new_credit_only(*vote_pubkey, false),
|
||||||
AccountMeta::new_credit_only(sysvar::clock::id(), false),
|
AccountMeta::new_credit_only(sysvar::clock::id(), false),
|
||||||
|
AccountMeta::new_credit_only(crate::config::id(), false),
|
||||||
];
|
];
|
||||||
Instruction::new(id(), &StakeInstruction::DelegateStake(stake), account_metas)
|
Instruction::new(id(), &StakeInstruction::DelegateStake(stake), account_metas)
|
||||||
}
|
}
|
||||||
@ -139,12 +143,17 @@ pub fn process_instruction(
|
|||||||
// TODO: data-driven unpack and dispatch of KeyedAccounts
|
// TODO: data-driven unpack and dispatch of KeyedAccounts
|
||||||
match deserialize(data).map_err(|_| InstructionError::InvalidInstructionData)? {
|
match deserialize(data).map_err(|_| InstructionError::InvalidInstructionData)? {
|
||||||
StakeInstruction::DelegateStake(stake) => {
|
StakeInstruction::DelegateStake(stake) => {
|
||||||
if rest.len() != 2 {
|
if rest.len() != 3 {
|
||||||
Err(InstructionError::InvalidInstructionData)?;
|
Err(InstructionError::InvalidInstructionData)?;
|
||||||
}
|
}
|
||||||
let vote = &rest[0];
|
let vote = &rest[0];
|
||||||
|
|
||||||
me.delegate_stake(vote, stake, &sysvar::clock::from_keyed_account(&rest[1])?)
|
me.delegate_stake(
|
||||||
|
vote,
|
||||||
|
stake,
|
||||||
|
&sysvar::clock::from_keyed_account(&rest[1])?,
|
||||||
|
&config::from_keyed_account(&rest[2])?,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
StakeInstruction::RedeemVoteCredits => {
|
StakeInstruction::RedeemVoteCredits => {
|
||||||
if rest.len() != 4 {
|
if rest.len() != 4 {
|
||||||
@ -206,6 +215,8 @@ mod tests {
|
|||||||
sysvar::rewards::create_account(1, 0.0, 0.0)
|
sysvar::rewards::create_account(1, 0.0, 0.0)
|
||||||
} else if sysvar::stake_history::check_id(&meta.pubkey) {
|
} else if sysvar::stake_history::check_id(&meta.pubkey) {
|
||||||
sysvar::stake_history::create_account(1, &StakeHistory::default())
|
sysvar::stake_history::create_account(1, &StakeHistory::default())
|
||||||
|
} else if config::check_id(&meta.pubkey) {
|
||||||
|
config::create_account(1, &config::Config::default())
|
||||||
} else {
|
} else {
|
||||||
Account::default()
|
Account::default()
|
||||||
}
|
}
|
||||||
@ -299,6 +310,11 @@ mod tests {
|
|||||||
false,
|
false,
|
||||||
&mut sysvar::clock::create_account(1, 0, 0, 0, 0)
|
&mut sysvar::clock::create_account(1, 0, 0, 0, 0)
|
||||||
),
|
),
|
||||||
|
KeyedAccount::new(
|
||||||
|
&config::id(),
|
||||||
|
false,
|
||||||
|
&mut config::create_account(1, &config::Config::default())
|
||||||
|
),
|
||||||
],
|
],
|
||||||
&serialize(&StakeInstruction::DelegateStake(0)).unwrap(),
|
&serialize(&StakeInstruction::DelegateStake(0)).unwrap(),
|
||||||
),
|
),
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
//! * keep track of rewards
|
//! * keep track of rewards
|
||||||
//! * own mining pools
|
//! * own mining pools
|
||||||
|
|
||||||
use crate::id;
|
use crate::{config::Config, id};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::{Account, KeyedAccount},
|
account::{Account, KeyedAccount},
|
||||||
@ -56,10 +56,9 @@ pub struct Stake {
|
|||||||
pub stake: u64, // stake amount activated
|
pub stake: u64, // stake amount activated
|
||||||
pub activated: Epoch, // epoch the stake was activated, std::Epoch::MAX if is a bootstrap stake
|
pub activated: Epoch, // epoch the stake was activated, std::Epoch::MAX if is a bootstrap stake
|
||||||
pub deactivated: Epoch, // epoch the stake was deactivated, std::Epoch::MAX if not deactivated
|
pub deactivated: Epoch, // epoch the stake was deactivated, std::Epoch::MAX if not deactivated
|
||||||
|
pub config: Config,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const STAKE_WARMUP_RATE: f64 = 0.15;
|
|
||||||
|
|
||||||
impl Default for Stake {
|
impl Default for Stake {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -68,6 +67,7 @@ impl Default for Stake {
|
|||||||
stake: 0,
|
stake: 0,
|
||||||
activated: 0,
|
activated: 0,
|
||||||
deactivated: std::u64::MAX,
|
deactivated: std::u64::MAX,
|
||||||
|
config: Config::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,7 +109,7 @@ impl Stake {
|
|||||||
|
|
||||||
// portion of activating stake in this epoch I'm entitled to
|
// portion of activating stake in this epoch I'm entitled to
|
||||||
effective_stake +=
|
effective_stake +=
|
||||||
(weight * entry.effective as f64 * STAKE_WARMUP_RATE) as u64;
|
(weight * entry.effective as f64 * self.config.warmup_rate) as u64;
|
||||||
|
|
||||||
if effective_stake >= self.stake {
|
if effective_stake >= self.stake {
|
||||||
effective_stake = self.stake;
|
effective_stake = self.stake;
|
||||||
@ -210,12 +210,19 @@ impl Stake {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn new(stake: u64, voter_pubkey: &Pubkey, vote_state: &VoteState, activated: Epoch) -> Self {
|
fn new(
|
||||||
|
stake: u64,
|
||||||
|
voter_pubkey: &Pubkey,
|
||||||
|
vote_state: &VoteState,
|
||||||
|
activated: Epoch,
|
||||||
|
config: &Config,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
stake,
|
stake,
|
||||||
activated,
|
activated,
|
||||||
voter_pubkey: *voter_pubkey,
|
voter_pubkey: *voter_pubkey,
|
||||||
credits_observed: vote_state.credits(),
|
credits_observed: vote_state.credits(),
|
||||||
|
config: *config,
|
||||||
..Stake::default()
|
..Stake::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -231,6 +238,7 @@ pub trait StakeAccount {
|
|||||||
vote_account: &KeyedAccount,
|
vote_account: &KeyedAccount,
|
||||||
stake: u64,
|
stake: u64,
|
||||||
clock: &sysvar::clock::Clock,
|
clock: &sysvar::clock::Clock,
|
||||||
|
config: &Config,
|
||||||
) -> Result<(), InstructionError>;
|
) -> Result<(), InstructionError>;
|
||||||
fn deactivate_stake(
|
fn deactivate_stake(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -259,6 +267,7 @@ impl<'a> StakeAccount for KeyedAccount<'a> {
|
|||||||
vote_account: &KeyedAccount,
|
vote_account: &KeyedAccount,
|
||||||
new_stake: u64,
|
new_stake: u64,
|
||||||
clock: &sysvar::clock::Clock,
|
clock: &sysvar::clock::Clock,
|
||||||
|
config: &Config,
|
||||||
) -> Result<(), InstructionError> {
|
) -> Result<(), InstructionError> {
|
||||||
if self.signer_key().is_none() {
|
if self.signer_key().is_none() {
|
||||||
return Err(InstructionError::MissingRequiredSignature);
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
@ -274,6 +283,7 @@ impl<'a> StakeAccount for KeyedAccount<'a> {
|
|||||||
vote_account.unsigned_key(),
|
vote_account.unsigned_key(),
|
||||||
&vote_account.state()?,
|
&vote_account.state()?,
|
||||||
clock.epoch,
|
clock.epoch,
|
||||||
|
config,
|
||||||
);
|
);
|
||||||
|
|
||||||
self.set_state(&StakeState::Stake(stake))
|
self.set_state(&StakeState::Stake(stake))
|
||||||
@ -381,10 +391,6 @@ impl<'a> StakeAccount for KeyedAccount<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//find_min<'a, I>(vals: I) -> Option<&'a u32>
|
|
||||||
//where
|
|
||||||
// I: Iterator<Item = &'a u32>,
|
|
||||||
|
|
||||||
// utility function, used by runtime::Stakes, tests
|
// utility function, used by runtime::Stakes, tests
|
||||||
pub fn new_stake_history_entry<'a, I>(
|
pub fn new_stake_history_entry<'a, I>(
|
||||||
epoch: Epoch,
|
epoch: Epoch,
|
||||||
@ -429,11 +435,6 @@ pub fn create_stake_account(
|
|||||||
stake_account
|
stake_account
|
||||||
}
|
}
|
||||||
|
|
||||||
// utility function, used by Bank, tests, genesis
|
|
||||||
pub fn create_rewards_pool() -> Account {
|
|
||||||
Account::new_data(std::u64::MAX, &StakeState::RewardsPool, &crate::id()).unwrap()
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
@ -506,14 +507,19 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stake_keyed_account.delegate_stake(&vote_keyed_account, 0, &clock),
|
stake_keyed_account.delegate_stake(&vote_keyed_account, 0, &clock, &Config::default()),
|
||||||
Err(InstructionError::MissingRequiredSignature)
|
Err(InstructionError::MissingRequiredSignature)
|
||||||
);
|
);
|
||||||
|
|
||||||
// signed keyed account
|
// signed keyed account
|
||||||
let mut stake_keyed_account = KeyedAccount::new(&stake_pubkey, true, &mut stake_account);
|
let mut stake_keyed_account = KeyedAccount::new(&stake_pubkey, true, &mut stake_account);
|
||||||
assert!(stake_keyed_account
|
assert!(stake_keyed_account
|
||||||
.delegate_stake(&vote_keyed_account, stake_lamports, &clock)
|
.delegate_stake(
|
||||||
|
&vote_keyed_account,
|
||||||
|
stake_lamports,
|
||||||
|
&clock,
|
||||||
|
&Config::default()
|
||||||
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
|
|
||||||
// verify that delegate_stake() looks right, compare against hand-rolled
|
// verify that delegate_stake() looks right, compare against hand-rolled
|
||||||
@ -526,19 +532,30 @@ mod tests {
|
|||||||
stake: stake_lamports,
|
stake: stake_lamports,
|
||||||
activated: clock.epoch,
|
activated: clock.epoch,
|
||||||
deactivated: std::u64::MAX,
|
deactivated: std::u64::MAX,
|
||||||
|
config: Config::default()
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
// verify that delegate_stake can't be called twice StakeState::default()
|
// verify that delegate_stake can't be called twice StakeState::default()
|
||||||
// signed keyed account
|
// signed keyed account
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stake_keyed_account.delegate_stake(&vote_keyed_account, stake_lamports, &clock),
|
stake_keyed_account.delegate_stake(
|
||||||
|
&vote_keyed_account,
|
||||||
|
stake_lamports,
|
||||||
|
&clock,
|
||||||
|
&Config::default()
|
||||||
|
),
|
||||||
Err(InstructionError::InvalidAccountData)
|
Err(InstructionError::InvalidAccountData)
|
||||||
);
|
);
|
||||||
|
|
||||||
// verify can only stake up to account lamports
|
// verify can only stake up to account lamports
|
||||||
let mut stake_keyed_account = KeyedAccount::new(&stake_pubkey, true, &mut stake_account);
|
let mut stake_keyed_account = KeyedAccount::new(&stake_pubkey, true, &mut stake_account);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stake_keyed_account.delegate_stake(&vote_keyed_account, stake_lamports + 1, &clock),
|
stake_keyed_account.delegate_stake(
|
||||||
|
&vote_keyed_account,
|
||||||
|
stake_lamports + 1,
|
||||||
|
&clock,
|
||||||
|
&Config::default()
|
||||||
|
),
|
||||||
Err(InstructionError::InsufficientFunds)
|
Err(InstructionError::InsufficientFunds)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -546,7 +563,7 @@ mod tests {
|
|||||||
|
|
||||||
stake_keyed_account.set_state(&stake_state).unwrap();
|
stake_keyed_account.set_state(&stake_state).unwrap();
|
||||||
assert!(stake_keyed_account
|
assert!(stake_keyed_account
|
||||||
.delegate_stake(&vote_keyed_account, 0, &clock)
|
.delegate_stake(&vote_keyed_account, 0, &clock, &Config::default())
|
||||||
.is_err());
|
.is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -608,7 +625,9 @@ mod tests {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
assert!(epoch < epochs); // should have warmed everything up by this time
|
assert!(epoch < epochs); // should have warmed everything up by this time
|
||||||
assert!(delta as f64 / prev_total_effective_stake as f64 <= STAKE_WARMUP_RATE);
|
assert!(
|
||||||
|
delta as f64 / prev_total_effective_stake as f64 <= Config::default().warmup_rate
|
||||||
|
);
|
||||||
prev_total_effective_stake = total_effective_stake;
|
prev_total_effective_stake = total_effective_stake;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -651,7 +670,12 @@ mod tests {
|
|||||||
let mut vote_keyed_account = KeyedAccount::new(&vote_pubkey, false, &mut vote_account);
|
let mut vote_keyed_account = KeyedAccount::new(&vote_pubkey, false, &mut vote_account);
|
||||||
vote_keyed_account.set_state(&VoteState::default()).unwrap();
|
vote_keyed_account.set_state(&VoteState::default()).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stake_keyed_account.delegate_stake(&vote_keyed_account, stake_lamports, &clock),
|
stake_keyed_account.delegate_stake(
|
||||||
|
&vote_keyed_account,
|
||||||
|
stake_lamports,
|
||||||
|
&clock,
|
||||||
|
&Config::default()
|
||||||
|
),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -723,7 +747,12 @@ mod tests {
|
|||||||
let mut vote_keyed_account = KeyedAccount::new(&vote_pubkey, false, &mut vote_account);
|
let mut vote_keyed_account = KeyedAccount::new(&vote_pubkey, false, &mut vote_account);
|
||||||
vote_keyed_account.set_state(&VoteState::default()).unwrap();
|
vote_keyed_account.set_state(&VoteState::default()).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stake_keyed_account.delegate_stake(&vote_keyed_account, stake_lamports, &clock),
|
stake_keyed_account.delegate_stake(
|
||||||
|
&vote_keyed_account,
|
||||||
|
stake_lamports,
|
||||||
|
&clock,
|
||||||
|
&Config::default()
|
||||||
|
),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -810,7 +839,12 @@ mod tests {
|
|||||||
let mut vote_keyed_account = KeyedAccount::new(&vote_pubkey, false, &mut vote_account);
|
let mut vote_keyed_account = KeyedAccount::new(&vote_pubkey, false, &mut vote_account);
|
||||||
vote_keyed_account.set_state(&VoteState::default()).unwrap();
|
vote_keyed_account.set_state(&VoteState::default()).unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stake_keyed_account.delegate_stake(&vote_keyed_account, stake_lamports, &future),
|
stake_keyed_account.delegate_stake(
|
||||||
|
&vote_keyed_account,
|
||||||
|
stake_lamports,
|
||||||
|
&future,
|
||||||
|
&Config::default()
|
||||||
|
),
|
||||||
Ok(())
|
Ok(())
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -944,7 +978,12 @@ mod tests {
|
|||||||
rewards.validator_point_value = 100.0;
|
rewards.validator_point_value = 100.0;
|
||||||
|
|
||||||
let rewards_pool_pubkey = Pubkey::new_rand();
|
let rewards_pool_pubkey = Pubkey::new_rand();
|
||||||
let mut rewards_pool_account = create_rewards_pool();
|
let mut rewards_pool_account = Account::new_data(
|
||||||
|
std::u64::MAX,
|
||||||
|
&StakeState::RewardsPool,
|
||||||
|
&crate::rewards_pools::id(),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
let mut rewards_pool_keyed_account =
|
let mut rewards_pool_keyed_account =
|
||||||
KeyedAccount::new(&rewards_pool_pubkey, false, &mut rewards_pool_account);
|
KeyedAccount::new(&rewards_pool_pubkey, false, &mut rewards_pool_account);
|
||||||
|
|
||||||
@ -972,7 +1011,12 @@ mod tests {
|
|||||||
|
|
||||||
// delegate the stake
|
// delegate the stake
|
||||||
assert!(stake_keyed_account
|
assert!(stake_keyed_account
|
||||||
.delegate_stake(&vote_keyed_account, stake_lamports, &clock)
|
.delegate_stake(
|
||||||
|
&vote_keyed_account,
|
||||||
|
stake_lamports,
|
||||||
|
&clock,
|
||||||
|
&Config::default()
|
||||||
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
|
|
||||||
let stake_history = create_stake_history_from_stakes(
|
let stake_history = create_stake_history_from_stakes(
|
||||||
|
@ -74,7 +74,7 @@ pub fn create_genesis_block_with_leader(
|
|||||||
])
|
])
|
||||||
.fee_calculator(FeeCalculator::new(0)); // most tests don't want fees
|
.fee_calculator(FeeCalculator::new(0)); // most tests don't want fees
|
||||||
|
|
||||||
builder = solana_stake_api::rewards_pools::genesis(builder);
|
builder = solana_stake_api::genesis(builder);
|
||||||
builder = solana_storage_api::rewards_pools::genesis(builder);
|
builder = solana_storage_api::rewards_pools::genesis(builder);
|
||||||
|
|
||||||
GenesisBlockInfo {
|
GenesisBlockInfo {
|
||||||
|
Reference in New Issue
Block a user