add MiningPools, fund validator MiningPools from inflation (#4676)

* add MiningPool fund validator MinigPools from inflation

* fixup

* finish rename of MINIMUM_SLOT_LENGTH to MINIMUM_SLOTS_PER_EPOCH

* deterministic miningpool location

* point_value, not credit_value... use f64
This commit is contained in:
Rob Walker
2019-06-14 11:38:37 -07:00
committed by GitHub
parent 589a9d3a72
commit 4c6a6d63bf
12 changed files with 366 additions and 89 deletions

View File

@ -11,7 +11,7 @@ use solana_sdk::instruction::InstructionError;
use solana_sdk::pubkey::Pubkey;
use solana_vote_api::vote_state::VoteState;
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub enum StakeState {
Uninitialized,
Stake {
@ -19,7 +19,13 @@ pub enum StakeState {
credits_observed: u64,
stake: u64,
},
MiningPool,
MiningPool {
/// epoch for which this Pool will redeem rewards
epoch: u64,
/// the number of lamports each point is worth
point_value: f64,
},
}
impl Default for StakeState {
@ -121,7 +127,10 @@ pub trait StakeAccount {
impl<'a> StakeAccount for KeyedAccount<'a> {
fn initialize_mining_pool(&mut self) -> Result<(), InstructionError> {
if let StakeState::Uninitialized = self.state()? {
self.set_state(&StakeState::MiningPool)
self.set_state(&StakeState::MiningPool {
epoch: 0,
point_value: 0.0,
})
} else {
Err(InstructionError::InvalidAccountData)
}
@ -167,7 +176,7 @@ impl<'a> StakeAccount for KeyedAccount<'a> {
vote_account: &mut KeyedAccount,
) -> Result<(), InstructionError> {
if let (
StakeState::MiningPool,
StakeState::MiningPool { .. },
StakeState::Stake {
voter_pubkey,
credits_observed,
@ -231,6 +240,17 @@ pub fn create_stake_account(
stake_account
}
// utility function, used by Bank, tests, genesis
pub fn create_mining_pool(lamports: u64, epoch: u64, point_value: f64) -> Account {
let mut mining_pool_account = Account::new(lamports, std::mem::size_of::<StakeState>(), &id());
mining_pool_account
.set_state(&StakeState::MiningPool { epoch, point_value })
.expect("set_state");
mining_pool_account
}
#[cfg(test)]
mod tests {
use super::*;
@ -301,7 +321,10 @@ mod tests {
}
);
let stake_state = StakeState::MiningPool;
let stake_state = StakeState::MiningPool {
epoch: 0,
point_value: 0.0,
};
stake_keyed_account.set_state(&stake_state).unwrap();
assert!(stake_keyed_account
.delegate_stake(&vote_keyed_account, 0)
@ -395,7 +418,10 @@ mod tests {
);
mining_pool_keyed_account
.set_state(&StakeState::MiningPool)
.set_state(&StakeState::MiningPool {
epoch: 0,
point_value: 0.0,
})
.unwrap();
// no movement in vote account, so no redemption needed
@ -459,7 +485,10 @@ mod tests {
let mut mining_pool_keyed_account =
KeyedAccount::new(&pubkey, true, &mut mining_pool_account);
mining_pool_keyed_account
.set_state(&StakeState::MiningPool)
.set_state(&StakeState::MiningPool {
epoch: 0,
point_value: 0.0,
})
.unwrap();
let mut vote_state = VoteState::default();

View File

@ -97,7 +97,12 @@ impl VoteState {
// utility function, used by Stakes, tests
pub fn from(account: &Account) -> Option<VoteState> {
account.state().ok()
Self::deserialize(&account.data).ok()
}
// utility function, used by Stakes, tests
pub fn to(&self, account: &mut Account) -> Option<()> {
Self::serialize(self, &mut account.data).ok()
}
pub fn deserialize(input: &[u8]) -> Result<Self, InstructionError> {
@ -111,6 +116,11 @@ impl VoteState {
})
}
// utility function, used by Stakes, tests
pub fn credits_from(account: &Account) -> Option<u64> {
Self::from(account).map(|state| state.credits())
}
/// returns commission split as (voter_portion, staker_portion, was_split) tuple
///
/// if commission calculation is 100% one way or other,