add create_delegate_stake_account (#4197)

This commit is contained in:
Rob Walker 2019-05-07 17:08:49 -07:00 committed by GitHub
parent 69eeb7cf08
commit 401764ddb1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 121 additions and 17 deletions

1
Cargo.lock generated
View File

@ -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",
] ]

View File

@ -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"]

View File

@ -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),
);
} }
} }

View File

@ -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