add create_delegate_stake_account (#4197)
This commit is contained in:
parent
69eeb7cf08
commit
401764ddb1
|
@ -2649,7 +2649,6 @@ dependencies = [
|
||||||
"serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"solana-logger 0.15.0",
|
"solana-logger 0.15.0",
|
||||||
"solana-metrics 0.15.0",
|
"solana-metrics 0.15.0",
|
||||||
"solana-runtime 0.15.0",
|
|
||||||
"solana-sdk 0.15.0",
|
"solana-sdk 0.15.0",
|
||||||
"solana-vote-api 0.15.0",
|
"solana-vote-api 0.15.0",
|
||||||
]
|
]
|
||||||
|
|
|
@ -18,9 +18,6 @@ solana-metrics = { path = "../../metrics", version = "0.15.0" }
|
||||||
solana-sdk = { path = "../../sdk", version = "0.15.0" }
|
solana-sdk = { path = "../../sdk", version = "0.15.0" }
|
||||||
solana-vote-api = { path = "../vote_api", version = "0.15.0" }
|
solana-vote-api = { path = "../vote_api", version = "0.15.0" }
|
||||||
|
|
||||||
[dev-dependencies]
|
|
||||||
solana-runtime = { path = "../../runtime", version = "0.15.0" }
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "solana_stake_api"
|
name = "solana_stake_api"
|
||||||
crate-type = ["lib"]
|
crate-type = ["lib"]
|
||||||
|
|
|
@ -22,14 +22,14 @@ pub enum StakeInstruction {
|
||||||
RedeemVoteCredits,
|
RedeemVoteCredits,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_account(from_id: &Pubkey, staker_id: &Pubkey, lamports: u64) -> Vec<Instruction> {
|
pub fn create_account(from_id: &Pubkey, staker_id: &Pubkey, lamports: u64) -> Instruction {
|
||||||
vec![system_instruction::create_account(
|
system_instruction::create_account(
|
||||||
from_id,
|
from_id,
|
||||||
staker_id,
|
staker_id,
|
||||||
lamports,
|
lamports,
|
||||||
std::mem::size_of::<StakeState>() as u64,
|
std::mem::size_of::<StakeState>() as u64,
|
||||||
&id(),
|
&id(),
|
||||||
)]
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn redeem_vote_credits(
|
pub fn redeem_vote_credits(
|
||||||
|
@ -104,13 +104,59 @@ mod tests {
|
||||||
use bincode::serialize;
|
use bincode::serialize;
|
||||||
use solana_sdk::account::Account;
|
use solana_sdk::account::Account;
|
||||||
|
|
||||||
|
fn process_instruction(instruction: &Instruction) -> Result<(), InstructionError> {
|
||||||
|
let mut accounts = vec![];
|
||||||
|
for _ in 0..instruction.accounts.len() {
|
||||||
|
accounts.push(Account::default());
|
||||||
|
}
|
||||||
|
{
|
||||||
|
let mut keyed_accounts: Vec<_> = instruction
|
||||||
|
.accounts
|
||||||
|
.iter()
|
||||||
|
.zip(accounts.iter_mut())
|
||||||
|
.map(|(meta, account)| KeyedAccount::new(&meta.pubkey, meta.is_signer, account))
|
||||||
|
.collect();
|
||||||
|
super::process_instruction(
|
||||||
|
&Pubkey::default(),
|
||||||
|
&mut keyed_accounts,
|
||||||
|
&instruction.data,
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_stake_process_instruction() {
|
||||||
|
assert_eq!(
|
||||||
|
process_instruction(&create_account(&Pubkey::default(), &Pubkey::default(), 0)),
|
||||||
|
Err(InstructionError::InvalidInstructionData) // won't even decode ;)
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
process_instruction(&redeem_vote_credits(
|
||||||
|
&Pubkey::default(),
|
||||||
|
&Pubkey::default(),
|
||||||
|
&Pubkey::default(),
|
||||||
|
&Pubkey::default()
|
||||||
|
)),
|
||||||
|
Err(InstructionError::InvalidAccountData),
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
process_instruction(&delegate_stake(
|
||||||
|
&Pubkey::default(),
|
||||||
|
&Pubkey::default(),
|
||||||
|
&Pubkey::default()
|
||||||
|
)),
|
||||||
|
Err(InstructionError::InvalidAccountData),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_stake_process_instruction_decode_bail() {
|
fn test_stake_process_instruction_decode_bail() {
|
||||||
// these will not call stake_state, have bogus contents
|
// these will not call stake_state, have bogus contents
|
||||||
|
|
||||||
// gets the first check
|
// gets the first check
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
super::process_instruction(
|
||||||
&Pubkey::default(),
|
&Pubkey::default(),
|
||||||
&mut [KeyedAccount::new(
|
&mut [KeyedAccount::new(
|
||||||
&Pubkey::default(),
|
&Pubkey::default(),
|
||||||
|
@ -123,12 +169,12 @@ mod tests {
|
||||||
Err(InstructionError::InvalidInstructionData),
|
Err(InstructionError::InvalidInstructionData),
|
||||||
);
|
);
|
||||||
|
|
||||||
// gets the check in delegate_stake
|
// gets the sub-check for number of args
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
super::process_instruction(
|
||||||
&Pubkey::default(),
|
&Pubkey::default(),
|
||||||
&mut [
|
&mut [
|
||||||
KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()),
|
KeyedAccount::new(&Pubkey::default(), true, &mut Account::default()),
|
||||||
KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()),
|
KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()),
|
||||||
],
|
],
|
||||||
&serialize(&StakeInstruction::DelegateStake).unwrap(),
|
&serialize(&StakeInstruction::DelegateStake).unwrap(),
|
||||||
|
@ -137,9 +183,8 @@ mod tests {
|
||||||
Err(InstructionError::InvalidInstructionData),
|
Err(InstructionError::InvalidInstructionData),
|
||||||
);
|
);
|
||||||
|
|
||||||
// gets the check in redeem_vote_credits
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
process_instruction(
|
super::process_instruction(
|
||||||
&Pubkey::default(),
|
&Pubkey::default(),
|
||||||
&mut [
|
&mut [
|
||||||
KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()),
|
KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()),
|
||||||
|
@ -151,6 +196,37 @@ mod tests {
|
||||||
),
|
),
|
||||||
Err(InstructionError::InvalidInstructionData),
|
Err(InstructionError::InvalidInstructionData),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// gets the check in delegate_stake
|
||||||
|
assert_eq!(
|
||||||
|
super::process_instruction(
|
||||||
|
&Pubkey::default(),
|
||||||
|
&mut [
|
||||||
|
KeyedAccount::new(&Pubkey::default(), true, &mut Account::default()), // from
|
||||||
|
KeyedAccount::new(&Pubkey::default(), true, &mut Account::default()),
|
||||||
|
KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()),
|
||||||
|
],
|
||||||
|
&serialize(&StakeInstruction::DelegateStake).unwrap(),
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
Err(InstructionError::InvalidAccountData),
|
||||||
|
);
|
||||||
|
|
||||||
|
// gets the check in redeem_vote_credits
|
||||||
|
assert_eq!(
|
||||||
|
super::process_instruction(
|
||||||
|
&Pubkey::default(),
|
||||||
|
&mut [
|
||||||
|
KeyedAccount::new(&Pubkey::default(), true, &mut Account::default()), // from
|
||||||
|
KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()),
|
||||||
|
KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()),
|
||||||
|
KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()),
|
||||||
|
],
|
||||||
|
&serialize(&StakeInstruction::RedeemVoteCredits).unwrap(),
|
||||||
|
0,
|
||||||
|
),
|
||||||
|
Err(InstructionError::InvalidAccountData),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,9 @@
|
||||||
//! * keep track of rewards
|
//! * keep track of rewards
|
||||||
//! * own mining pools
|
//! * own mining pools
|
||||||
|
|
||||||
//use crate::{check_id, id};
|
use crate::id;
|
||||||
//use log::*;
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use solana_sdk::account::KeyedAccount;
|
use solana_sdk::account::{Account, KeyedAccount};
|
||||||
use solana_sdk::instruction::InstructionError;
|
use solana_sdk::instruction::InstructionError;
|
||||||
use solana_sdk::instruction_processor_utils::State;
|
use solana_sdk::instruction_processor_utils::State;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
|
@ -40,7 +39,7 @@ const CREDITS_PER_YEAR: f64 = (365f64 * 24f64 * 3600f64) * TICKS_PER_SECOND / TI
|
||||||
const STAKE_REWARD_TARGET_RATE: f64 = 0.20;
|
const STAKE_REWARD_TARGET_RATE: f64 = 0.20;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
const STAKE_GETS_PAID_EVERY_VOTE: u64 = 200_000_000; // if numbers above move, fix this
|
const STAKE_GETS_PAID_EVERY_VOTE: u64 = 200_000_000; // if numbers above (TICKS_YEAR) move, fix this
|
||||||
|
|
||||||
impl StakeState {
|
impl StakeState {
|
||||||
pub fn calculate_rewards(
|
pub fn calculate_rewards(
|
||||||
|
@ -148,6 +147,24 @@ impl<'a> StakeAccount for KeyedAccount<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// utility function, used by Bank, tests, genesis
|
||||||
|
pub fn create_delegate_stake_account(
|
||||||
|
voter_id: &Pubkey,
|
||||||
|
vote_state: &VoteState,
|
||||||
|
lamports: u64,
|
||||||
|
) -> Account {
|
||||||
|
let mut stake_account = Account::new(lamports, std::mem::size_of::<StakeState>(), &id());
|
||||||
|
|
||||||
|
stake_account
|
||||||
|
.set_state(&StakeState::Delegate {
|
||||||
|
voter_id: *voter_id,
|
||||||
|
credits_observed: vote_state.credits(),
|
||||||
|
})
|
||||||
|
.expect("set_state");
|
||||||
|
|
||||||
|
stake_account
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -159,6 +176,8 @@ mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_stake_delegate_stake() {
|
fn test_stake_delegate_stake() {
|
||||||
|
dbg!(std::env::var("CARGO_FOO").unwrap_or("not set".to_string()));
|
||||||
|
|
||||||
let vote_keypair = Keypair::new();
|
let vote_keypair = Keypair::new();
|
||||||
let mut vote_state = VoteState::default();
|
let mut vote_state = VoteState::default();
|
||||||
for i in 0..1000 {
|
for i in 0..1000 {
|
||||||
|
@ -176,6 +195,11 @@ mod tests {
|
||||||
|
|
||||||
let mut stake_keyed_account = KeyedAccount::new(&stake_pubkey, false, &mut stake_account);
|
let mut stake_keyed_account = KeyedAccount::new(&stake_pubkey, false, &mut stake_account);
|
||||||
|
|
||||||
|
{
|
||||||
|
let stake_state: StakeState = stake_keyed_account.state().unwrap();
|
||||||
|
assert_eq!(stake_state, StakeState::default());
|
||||||
|
}
|
||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stake_keyed_account.delegate_stake(&vote_keyed_account),
|
stake_keyed_account.delegate_stake(&vote_keyed_account),
|
||||||
Err(InstructionError::MissingRequiredSignature)
|
Err(InstructionError::MissingRequiredSignature)
|
||||||
|
@ -186,6 +210,13 @@ mod tests {
|
||||||
.delegate_stake(&vote_keyed_account)
|
.delegate_stake(&vote_keyed_account)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
|
|
||||||
|
// verify that create_delegate_stake_account() matches the
|
||||||
|
// resulting account from delegate_stake()
|
||||||
|
assert_eq!(
|
||||||
|
create_delegate_stake_account(&vote_pubkey, &vote_state, 0),
|
||||||
|
*stake_keyed_account.account,
|
||||||
|
);
|
||||||
|
|
||||||
let stake_state: StakeState = stake_keyed_account.state().unwrap();
|
let stake_state: StakeState = stake_keyed_account.state().unwrap();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
stake_state,
|
stake_state,
|
||||||
|
@ -194,6 +225,7 @@ mod tests {
|
||||||
credits_observed: vote_state.credits()
|
credits_observed: vote_state.credits()
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
let stake_state = StakeState::MiningPool;
|
let stake_state = StakeState::MiningPool;
|
||||||
stake_keyed_account.set_state(&stake_state).unwrap();
|
stake_keyed_account.set_state(&stake_state).unwrap();
|
||||||
assert!(stake_keyed_account
|
assert!(stake_keyed_account
|
||||||
|
|
Loading…
Reference in New Issue