make voter_pubkey a function of epoch (#5830)
* make voter_pubkey a function of epoch * fixups
This commit is contained in:
parent
7682db4826
commit
b881029de3
|
@ -6,32 +6,34 @@ use log::*;
|
||||||
use num_traits::FromPrimitive;
|
use num_traits::FromPrimitive;
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use serde_json::{json, Value};
|
use serde_json::{json, Value};
|
||||||
use solana_budget_api;
|
use solana_budget_api::budget_instruction::{self, BudgetError};
|
||||||
use solana_budget_api::budget_instruction;
|
|
||||||
use solana_budget_api::budget_state::BudgetError;
|
|
||||||
use solana_client::client_error::ClientError;
|
use solana_client::client_error::ClientError;
|
||||||
use solana_client::rpc_client::RpcClient;
|
use solana_client::rpc_client::RpcClient;
|
||||||
#[cfg(not(test))]
|
#[cfg(not(test))]
|
||||||
use solana_drone::drone::request_airdrop_transaction;
|
use solana_drone::drone::request_airdrop_transaction;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
use solana_drone::drone_mock::request_airdrop_transaction;
|
use solana_drone::drone_mock::request_airdrop_transaction;
|
||||||
use solana_sdk::account_utils::State;
|
use solana_sdk::{
|
||||||
use solana_sdk::bpf_loader;
|
account_utils::State,
|
||||||
use solana_sdk::fee_calculator::FeeCalculator;
|
bpf_loader,
|
||||||
use solana_sdk::hash::Hash;
|
fee_calculator::FeeCalculator,
|
||||||
use solana_sdk::instruction::InstructionError;
|
hash::Hash,
|
||||||
use solana_sdk::instruction_processor_utils::DecodeError;
|
instruction::InstructionError,
|
||||||
use solana_sdk::loader_instruction;
|
instruction_processor_utils::DecodeError,
|
||||||
use solana_sdk::message::Message;
|
loader_instruction,
|
||||||
use solana_sdk::pubkey::Pubkey;
|
message::Message,
|
||||||
use solana_sdk::signature::{read_keypair, Keypair, KeypairUtil, Signature};
|
pubkey::Pubkey,
|
||||||
use solana_sdk::system_instruction::SystemError;
|
signature::{read_keypair, Keypair, KeypairUtil, Signature},
|
||||||
use solana_sdk::system_transaction;
|
system_instruction::SystemError,
|
||||||
use solana_sdk::transaction::{Transaction, TransactionError};
|
system_transaction,
|
||||||
use solana_stake_api::{stake_instruction, stake_state::StakeError};
|
transaction::{Transaction, TransactionError},
|
||||||
|
};
|
||||||
|
use solana_stake_api::stake_instruction::{self, StakeError};
|
||||||
use solana_storage_api::storage_instruction;
|
use solana_storage_api::storage_instruction;
|
||||||
use solana_vote_api::vote_instruction;
|
use solana_vote_api::{
|
||||||
use solana_vote_api::vote_state::VoteState;
|
vote_instruction::{self, VoteError},
|
||||||
|
vote_state::VoteState,
|
||||||
|
};
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
@ -617,9 +619,9 @@ fn process_authorize_voter(
|
||||||
recent_blockhash,
|
recent_blockhash,
|
||||||
);
|
);
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
||||||
let signature_str = rpc_client
|
let result = rpc_client
|
||||||
.send_and_confirm_transaction(&mut tx, &[&config.keypair, &authorized_voter_keypair])?;
|
.send_and_confirm_transaction(&mut tx, &[&config.keypair, &authorized_voter_keypair]);
|
||||||
Ok(signature_str.to_string())
|
log_instruction_custom_error::<VoteError>(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_show_account(
|
fn process_show_account(
|
||||||
|
|
|
@ -1,13 +1,39 @@
|
||||||
use crate::budget_expr::BudgetExpr;
|
use crate::{budget_expr::BudgetExpr, budget_state::BudgetState, id};
|
||||||
use crate::budget_state::BudgetState;
|
|
||||||
use crate::id;
|
|
||||||
use bincode::serialized_size;
|
use bincode::serialized_size;
|
||||||
use chrono::prelude::{DateTime, Utc};
|
use chrono::prelude::{DateTime, Utc};
|
||||||
|
use num_derive::FromPrimitive;
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::{
|
||||||
use solana_sdk::instruction::{AccountMeta, Instruction};
|
hash::Hash,
|
||||||
use solana_sdk::pubkey::Pubkey;
|
instruction::{AccountMeta, Instruction},
|
||||||
use solana_sdk::system_instruction;
|
instruction_processor_utils::DecodeError,
|
||||||
|
pubkey::Pubkey,
|
||||||
|
system_instruction,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, FromPrimitive)]
|
||||||
|
pub enum BudgetError {
|
||||||
|
DestinationMissing,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> DecodeError<T> for BudgetError {
|
||||||
|
fn type_of() -> &'static str {
|
||||||
|
"BudgetError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for BudgetError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
match self {
|
||||||
|
BudgetError::DestinationMissing => "destination missing",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for BudgetError {}
|
||||||
|
|
||||||
/// A smart contract.
|
/// A smart contract.
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
//! budget program
|
//! budget program
|
||||||
use crate::budget_expr::Witness;
|
use crate::{
|
||||||
use crate::budget_instruction::BudgetInstruction;
|
budget_expr::Witness,
|
||||||
use crate::budget_state::{BudgetError, BudgetState};
|
budget_instruction::{BudgetError, BudgetInstruction},
|
||||||
|
budget_state::BudgetState,
|
||||||
|
};
|
||||||
use bincode::deserialize;
|
use bincode::deserialize;
|
||||||
use chrono::prelude::{DateTime, Utc};
|
use chrono::prelude::{DateTime, Utc};
|
||||||
use log::*;
|
use log::*;
|
||||||
use solana_sdk::account::KeyedAccount;
|
use solana_sdk::{
|
||||||
use solana_sdk::hash::hash;
|
account::KeyedAccount, hash::hash, instruction::InstructionError, pubkey::Pubkey,
|
||||||
use solana_sdk::instruction::InstructionError;
|
};
|
||||||
use solana_sdk::pubkey::Pubkey;
|
|
||||||
|
|
||||||
/// Process a Witness Signature. Any payment plans waiting on this signature
|
/// Process a Witness Signature. Any payment plans waiting on this signature
|
||||||
/// will progress one step.
|
/// will progress one step.
|
||||||
|
|
|
@ -1,28 +1,8 @@
|
||||||
//! budget state
|
//! budget state
|
||||||
use crate::budget_expr::BudgetExpr;
|
use crate::budget_expr::BudgetExpr;
|
||||||
use bincode::{self, deserialize, serialize_into};
|
use bincode::{self, deserialize, serialize_into};
|
||||||
use num_derive::FromPrimitive;
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use solana_sdk::instruction::InstructionError;
|
use solana_sdk::instruction::InstructionError;
|
||||||
use solana_sdk::instruction_processor_utils::DecodeError;
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, FromPrimitive)]
|
|
||||||
pub enum BudgetError {
|
|
||||||
DestinationMissing,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> DecodeError<T> for BudgetError {
|
|
||||||
fn type_of() -> &'static str {
|
|
||||||
"BudgetError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for BudgetError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
write!(f, "error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::error::Error for BudgetError {}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
|
#[derive(Serialize, Deserialize, Debug, Clone, Default, PartialEq)]
|
||||||
pub struct BudgetState {
|
pub struct BudgetState {
|
||||||
|
|
|
@ -4,15 +4,36 @@ use crate::{
|
||||||
};
|
};
|
||||||
use bincode::deserialize;
|
use bincode::deserialize;
|
||||||
use log::*;
|
use log::*;
|
||||||
|
use num_derive::{FromPrimitive, ToPrimitive};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::KeyedAccount,
|
account::KeyedAccount,
|
||||||
clock::Slot,
|
clock::Slot,
|
||||||
instruction::{AccountMeta, Instruction, InstructionError},
|
instruction::{AccountMeta, Instruction, InstructionError},
|
||||||
|
instruction_processor_utils::DecodeError,
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
system_instruction, sysvar,
|
system_instruction, sysvar,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Reasons the stake might have had an error
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, FromPrimitive, ToPrimitive)]
|
||||||
|
pub enum StakeError {
|
||||||
|
NoCreditsToRedeem,
|
||||||
|
}
|
||||||
|
impl<E> DecodeError<E> for StakeError {
|
||||||
|
fn type_of() -> &'static str {
|
||||||
|
"StakeError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::fmt::Display for StakeError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
StakeError::NoCreditsToRedeem => write!(f, "not enough credits to redeem"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for StakeError {}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum StakeInstruction {
|
pub enum StakeInstruction {
|
||||||
/// `Lockup` a stake until the specified slot
|
/// `Lockup` a stake until the specified slot
|
||||||
|
@ -454,4 +475,30 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_custom_error_decode() {
|
||||||
|
use num_traits::FromPrimitive;
|
||||||
|
fn pretty_err<T>(err: InstructionError) -> String
|
||||||
|
where
|
||||||
|
T: 'static + std::error::Error + DecodeError<T> + FromPrimitive,
|
||||||
|
{
|
||||||
|
if let InstructionError::CustomError(code) = err {
|
||||||
|
let specific_error: T = T::decode_custom_error_to_enum(code).unwrap();
|
||||||
|
format!(
|
||||||
|
"{:?}: {}::{:?} - {}",
|
||||||
|
err,
|
||||||
|
T::type_of(),
|
||||||
|
specific_error,
|
||||||
|
specific_error,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
"".to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert_eq!(
|
||||||
|
"CustomError(0): StakeError::NoCreditsToRedeem - not enough credits to redeem",
|
||||||
|
pretty_err::<StakeError>(StakeError::NoCreditsToRedeem.into())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,15 +3,13 @@
|
||||||
//! * keep track of rewards
|
//! * keep track of rewards
|
||||||
//! * own mining pools
|
//! * own mining pools
|
||||||
|
|
||||||
use crate::{config::Config, id};
|
use crate::{config::Config, id, stake_instruction::StakeError};
|
||||||
use num_derive::{FromPrimitive, ToPrimitive};
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
account::{Account, KeyedAccount},
|
account::{Account, KeyedAccount},
|
||||||
account_utils::State,
|
account_utils::State,
|
||||||
clock::{Epoch, Slot},
|
clock::{Epoch, Slot},
|
||||||
instruction::InstructionError,
|
instruction::InstructionError,
|
||||||
instruction_processor_utils::DecodeError,
|
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
sysvar::{
|
sysvar::{
|
||||||
self,
|
self,
|
||||||
|
@ -21,6 +19,7 @@ use solana_sdk::{
|
||||||
use solana_vote_api::vote_state::VoteState;
|
use solana_vote_api::vote_state::VoteState;
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
|
||||||
|
#[allow(clippy::large_enum_variant)]
|
||||||
pub enum StakeState {
|
pub enum StakeState {
|
||||||
Uninitialized,
|
Uninitialized,
|
||||||
Lockup(Slot),
|
Lockup(Slot),
|
||||||
|
@ -52,46 +51,46 @@ impl StakeState {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reasons the stake might have had an error
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, FromPrimitive, ToPrimitive)]
|
|
||||||
pub enum StakeError {
|
|
||||||
NoCreditsToRedeem,
|
|
||||||
}
|
|
||||||
impl<E> DecodeError<E> for StakeError {
|
|
||||||
fn type_of() -> &'static str {
|
|
||||||
"StakeError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::fmt::Display for StakeError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
match self {
|
|
||||||
StakeError::NoCreditsToRedeem => write!(f, "not enough credits to redeem"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::error::Error for StakeError {}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
|
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
|
||||||
pub struct Stake {
|
pub struct Stake {
|
||||||
|
/// most recently delegated vote account pubkey
|
||||||
pub voter_pubkey: Pubkey,
|
pub voter_pubkey: Pubkey,
|
||||||
|
/// the epoch when voter_pubkey was most recently set
|
||||||
|
pub voter_pubkey_epoch: Epoch,
|
||||||
|
/// credits observed is credits from vote account state when delegated or redeemed
|
||||||
pub credits_observed: u64,
|
pub credits_observed: u64,
|
||||||
pub stake: u64, // stake amount activated
|
/// activated stake amount, set at delegate_stake() time
|
||||||
pub activation_epoch: Epoch, // epoch the stake was activated, std::Epoch::MAX if is a bootstrap stake
|
pub stake: u64,
|
||||||
pub deactivation_epoch: Epoch, // epoch the stake was deactivated, std::Epoch::MAX if not deactivated
|
/// epoch at which this stake was activated, std::Epoch::MAX if is a bootstrap stake
|
||||||
|
pub activation_epoch: Epoch,
|
||||||
|
/// epoch the stake was deactivated, std::Epoch::MAX if not deactivated
|
||||||
|
pub deactivation_epoch: Epoch,
|
||||||
|
/// stake config (warmup, etc.)
|
||||||
pub config: Config,
|
pub config: Config,
|
||||||
|
/// the Slot at which this stake becomes available for withdrawal
|
||||||
pub lockup: Slot,
|
pub lockup: Slot,
|
||||||
|
/// history of prior delegates and the epoch ranges for which
|
||||||
|
/// they were set, circular buffer
|
||||||
|
pub prior_delegates: [(Pubkey, Epoch, Epoch); MAX_PRIOR_DELEGATES],
|
||||||
|
/// next pointer
|
||||||
|
pub prior_delegates_idx: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const MAX_PRIOR_DELEGATES: usize = 32;
|
||||||
|
|
||||||
impl Default for Stake {
|
impl Default for Stake {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
Self {
|
Self {
|
||||||
voter_pubkey: Pubkey::default(),
|
voter_pubkey: Pubkey::default(),
|
||||||
|
voter_pubkey_epoch: 0,
|
||||||
credits_observed: 0,
|
credits_observed: 0,
|
||||||
stake: 0,
|
stake: 0,
|
||||||
activation_epoch: 0,
|
activation_epoch: 0,
|
||||||
deactivation_epoch: std::u64::MAX,
|
deactivation_epoch: std::u64::MAX,
|
||||||
config: Config::default(),
|
config: Config::default(),
|
||||||
lockup: 0,
|
lockup: 0,
|
||||||
|
prior_delegates: <[(Pubkey, Epoch, Epoch); MAX_PRIOR_DELEGATES]>::default(),
|
||||||
|
prior_delegates_idx: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -105,6 +104,10 @@ impl Stake {
|
||||||
self.stake_activating_and_deactivating(epoch, history).0
|
self.stake_activating_and_deactivating(epoch, history).0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn voter_pubkey(&self, _epoch: Epoch) -> &Pubkey {
|
||||||
|
&self.voter_pubkey
|
||||||
|
}
|
||||||
|
|
||||||
fn stake_activating_and_deactivating(
|
fn stake_activating_and_deactivating(
|
||||||
&self,
|
&self,
|
||||||
epoch: Epoch,
|
epoch: Epoch,
|
||||||
|
@ -405,6 +408,8 @@ impl<'a> StakeAccount for KeyedAccount<'a> {
|
||||||
{
|
{
|
||||||
let vote_state: VoteState = vote_account.state()?;
|
let vote_state: VoteState = vote_account.state()?;
|
||||||
|
|
||||||
|
// the only valid use of current voter_pubkey, redelegation breaks
|
||||||
|
// rewards redemption for previous voter_pubkey
|
||||||
if stake.voter_pubkey != *vote_account.unsigned_key() {
|
if stake.voter_pubkey != *vote_account.unsigned_key() {
|
||||||
return Err(InstructionError::InvalidArgument);
|
return Err(InstructionError::InvalidArgument);
|
||||||
}
|
}
|
||||||
|
@ -633,8 +638,7 @@ mod tests {
|
||||||
stake: stake_lamports,
|
stake: stake_lamports,
|
||||||
activation_epoch: clock.epoch,
|
activation_epoch: clock.epoch,
|
||||||
deactivation_epoch: std::u64::MAX,
|
deactivation_epoch: std::u64::MAX,
|
||||||
config: Config::default(),
|
..Stake::default()
|
||||||
lockup: 0
|
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
// verify that delegate_stake can't be called twice StakeState::default()
|
// verify that delegate_stake can't be called twice StakeState::default()
|
||||||
|
@ -1257,32 +1261,6 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_custom_error_decode() {
|
|
||||||
use num_traits::FromPrimitive;
|
|
||||||
fn pretty_err<T>(err: InstructionError) -> String
|
|
||||||
where
|
|
||||||
T: 'static + std::error::Error + DecodeError<T> + FromPrimitive,
|
|
||||||
{
|
|
||||||
if let InstructionError::CustomError(code) = err {
|
|
||||||
let specific_error: T = T::decode_custom_error_to_enum(code).unwrap();
|
|
||||||
format!(
|
|
||||||
"{:?}: {}::{:?} - {}",
|
|
||||||
err,
|
|
||||||
T::type_of(),
|
|
||||||
specific_error,
|
|
||||||
specific_error,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
"".to_string()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert_eq!(
|
|
||||||
"CustomError(0): StakeError::NoCreditsToRedeem - not enough credits to redeem",
|
|
||||||
pretty_err::<StakeError>(StakeError::NoCreditsToRedeem.into())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_stake_state_calculate_rewards() {
|
fn test_stake_state_calculate_rewards() {
|
||||||
let mut vote_state = VoteState::default();
|
let mut vote_state = VoteState::default();
|
||||||
|
|
|
@ -1,17 +1,52 @@
|
||||||
//! Vote program
|
//! Vote program
|
||||||
//! Receive and processes votes from validators
|
//! Receive and processes votes from validators
|
||||||
|
|
||||||
use crate::id;
|
use crate::{
|
||||||
use crate::vote_state::{self, Vote, VoteState};
|
id,
|
||||||
|
vote_state::{self, Vote, VoteState},
|
||||||
|
};
|
||||||
use bincode::deserialize;
|
use bincode::deserialize;
|
||||||
use log::*;
|
use log::*;
|
||||||
|
use num_derive::{FromPrimitive, ToPrimitive};
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use solana_metrics::datapoint_warn;
|
use solana_metrics::datapoint_warn;
|
||||||
use solana_sdk::account::KeyedAccount;
|
use solana_sdk::{
|
||||||
use solana_sdk::instruction::{AccountMeta, Instruction, InstructionError};
|
account::KeyedAccount,
|
||||||
use solana_sdk::pubkey::Pubkey;
|
instruction::{AccountMeta, Instruction, InstructionError},
|
||||||
use solana_sdk::system_instruction;
|
instruction_processor_utils::DecodeError,
|
||||||
use solana_sdk::sysvar;
|
pubkey::Pubkey,
|
||||||
|
system_instruction, sysvar,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Reasons the stake might have had an error
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, FromPrimitive, ToPrimitive)]
|
||||||
|
pub enum VoteError {
|
||||||
|
VoteTooOld,
|
||||||
|
SlotsMismatch,
|
||||||
|
SlotHashMismatch,
|
||||||
|
EmptySlots,
|
||||||
|
}
|
||||||
|
impl<E> DecodeError<E> for VoteError {
|
||||||
|
fn type_of() -> &'static str {
|
||||||
|
"VoteError"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for VoteError {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||||
|
write!(
|
||||||
|
f,
|
||||||
|
"{}",
|
||||||
|
match self {
|
||||||
|
VoteError::VoteTooOld => "vote already recorded or not in slot hashes history",
|
||||||
|
VoteError::SlotsMismatch => "vote slots do not match bank history",
|
||||||
|
VoteError::SlotHashMismatch => "vote hash does not match bank hash",
|
||||||
|
VoteError::EmptySlots => "vote has no slots, invalid",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl std::error::Error for VoteError {}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum VoteInstruction {
|
pub enum VoteInstruction {
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
//! Vote state, vote program
|
//! Vote state, vote program
|
||||||
//! Receive and processes votes from validators
|
//! Receive and processes votes from validators
|
||||||
use crate::id;
|
use crate::{id, vote_instruction::VoteError};
|
||||||
use bincode::{deserialize, serialize_into, serialized_size, ErrorKind};
|
use bincode::{deserialize, serialize_into, serialized_size, ErrorKind};
|
||||||
use log::*;
|
use log::*;
|
||||||
use num_derive::{FromPrimitive, ToPrimitive};
|
|
||||||
use serde_derive::{Deserialize, Serialize};
|
use serde_derive::{Deserialize, Serialize};
|
||||||
use solana_sdk::sysvar::slot_hashes::SlotHash;
|
use solana_sdk::sysvar::slot_hashes::SlotHash;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
|
@ -12,7 +11,6 @@ use solana_sdk::{
|
||||||
clock::{Epoch, Slot},
|
clock::{Epoch, Slot},
|
||||||
hash::Hash,
|
hash::Hash,
|
||||||
instruction::InstructionError,
|
instruction::InstructionError,
|
||||||
instruction_processor_utils::DecodeError,
|
|
||||||
pubkey::Pubkey,
|
pubkey::Pubkey,
|
||||||
sysvar::clock::Clock,
|
sysvar::clock::Clock,
|
||||||
};
|
};
|
||||||
|
@ -26,36 +24,6 @@ pub const INITIAL_LOCKOUT: usize = 2;
|
||||||
// smaller numbers makes
|
// smaller numbers makes
|
||||||
pub const MAX_EPOCH_CREDITS_HISTORY: usize = 64;
|
pub const MAX_EPOCH_CREDITS_HISTORY: usize = 64;
|
||||||
|
|
||||||
/// Reasons the stake might have had an error
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, FromPrimitive, ToPrimitive)]
|
|
||||||
pub enum VoteError {
|
|
||||||
VoteTooOld,
|
|
||||||
SlotsMismatch,
|
|
||||||
SlotHashMismatch,
|
|
||||||
EmptySlots,
|
|
||||||
}
|
|
||||||
impl<E> DecodeError<E> for VoteError {
|
|
||||||
fn type_of() -> &'static str {
|
|
||||||
"VoteError"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl std::fmt::Display for VoteError {
|
|
||||||
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
|
|
||||||
write!(
|
|
||||||
f,
|
|
||||||
"{}",
|
|
||||||
match self {
|
|
||||||
VoteError::VoteTooOld => "vote already recorded or not in slot hashes history",
|
|
||||||
VoteError::SlotsMismatch => "vote slots do not match bank history",
|
|
||||||
VoteError::SlotHashMismatch => "vote hash does not match bank hash",
|
|
||||||
VoteError::EmptySlots => "vote has no slots, invalid",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
impl std::error::Error for VoteError {}
|
|
||||||
|
|
||||||
#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct Vote {
|
pub struct Vote {
|
||||||
/// A stack of votes starting with the oldest vote
|
/// A stack of votes starting with the oldest vote
|
||||||
|
|
|
@ -85,7 +85,7 @@ impl Stakes {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(_, stake_account)| {
|
.map(|(_, stake_account)| {
|
||||||
StakeState::stake_from(stake_account).map_or(0, |stake| {
|
StakeState::stake_from(stake_account).map_or(0, |stake| {
|
||||||
if stake.voter_pubkey == *voter_pubkey {
|
if stake.voter_pubkey(epoch) == voter_pubkey {
|
||||||
stake.stake(epoch, stake_history)
|
stake.stake(epoch, stake_history)
|
||||||
} else {
|
} else {
|
||||||
0
|
0
|
||||||
|
@ -129,7 +129,7 @@ impl Stakes {
|
||||||
let old_stake = self.stake_accounts.get(pubkey).and_then(|old_account| {
|
let old_stake = self.stake_accounts.get(pubkey).and_then(|old_account| {
|
||||||
StakeState::stake_from(old_account).map(|stake| {
|
StakeState::stake_from(old_account).map(|stake| {
|
||||||
(
|
(
|
||||||
stake.voter_pubkey,
|
*stake.voter_pubkey(self.epoch),
|
||||||
stake.stake(self.epoch, Some(&self.stake_history)),
|
stake.stake(self.epoch, Some(&self.stake_history)),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -137,7 +137,7 @@ impl Stakes {
|
||||||
|
|
||||||
let stake = StakeState::stake_from(account).map(|stake| {
|
let stake = StakeState::stake_from(account).map(|stake| {
|
||||||
(
|
(
|
||||||
stake.voter_pubkey,
|
*stake.voter_pubkey(self.epoch),
|
||||||
if account.lamports != 0 {
|
if account.lamports != 0 {
|
||||||
stake.stake(self.epoch, Some(&self.stake_history))
|
stake.stake(self.epoch, Some(&self.stake_history))
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue