Allow validators to accumulate credits for voting
This commit is contained in:
parent
6248624ee7
commit
549f9676f1
|
@ -39,19 +39,8 @@ fn process_vote(keyed_accounts: &mut [KeyedAccount], vote: Vote) -> Result<(), P
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut vote_state = VoteState::deserialize(&keyed_accounts[0].account.userdata)?;
|
let mut vote_state = VoteState::deserialize(&keyed_accounts[0].account.userdata)?;
|
||||||
|
vote_state.process_vote(vote);
|
||||||
// TODO: Integrity checks
|
|
||||||
// a) Verify the vote's bank hash matches what is expected
|
|
||||||
// b) Verify vote is older than previous votes
|
|
||||||
|
|
||||||
// Only keep around the most recent MAX_VOTE_HISTORY votes
|
|
||||||
if vote_state.votes.len() == vote_program::MAX_VOTE_HISTORY {
|
|
||||||
vote_state.votes.pop_front();
|
|
||||||
}
|
|
||||||
|
|
||||||
vote_state.votes.push_back(vote);
|
|
||||||
vote_state.serialize(&mut keyed_accounts[0].account.userdata)?;
|
vote_state.serialize(&mut keyed_accounts[0].account.userdata)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -152,6 +141,7 @@ mod tests {
|
||||||
let vote = Vote::new(1);
|
let vote = Vote::new(1);
|
||||||
let vote_state = vote_and_deserialize(&vote_id, &mut vote_account, vote.clone()).unwrap();
|
let vote_state = vote_and_deserialize(&vote_id, &mut vote_account, vote.clone()).unwrap();
|
||||||
assert_eq!(vote_state.votes, vec![vote]);
|
assert_eq!(vote_state.votes, vec![vote]);
|
||||||
|
assert_eq!(vote_state.credits(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
@ -20,7 +20,7 @@ pub fn id() -> Pubkey {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Maximum number of votes to keep around
|
// Maximum number of votes to keep around
|
||||||
pub const MAX_VOTE_HISTORY: usize = 32;
|
const MAX_VOTE_HISTORY: usize = 32;
|
||||||
|
|
||||||
#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)]
|
#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||||
pub struct Vote {
|
pub struct Vote {
|
||||||
|
@ -51,6 +51,7 @@ pub struct VoteState {
|
||||||
pub votes: VecDeque<Vote>,
|
pub votes: VecDeque<Vote>,
|
||||||
pub node_id: Pubkey,
|
pub node_id: Pubkey,
|
||||||
pub staker_id: Pubkey,
|
pub staker_id: Pubkey,
|
||||||
|
credits: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_max_size() -> usize {
|
pub fn get_max_size() -> usize {
|
||||||
|
@ -64,10 +65,12 @@ pub fn get_max_size() -> usize {
|
||||||
impl VoteState {
|
impl VoteState {
|
||||||
pub fn new(node_id: Pubkey, staker_id: Pubkey) -> Self {
|
pub fn new(node_id: Pubkey, staker_id: Pubkey) -> Self {
|
||||||
let votes = VecDeque::new();
|
let votes = VecDeque::new();
|
||||||
|
let credits = 0;
|
||||||
Self {
|
Self {
|
||||||
votes,
|
votes,
|
||||||
node_id,
|
node_id,
|
||||||
staker_id,
|
staker_id,
|
||||||
|
credits,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,6 +84,31 @@ impl VoteState {
|
||||||
_ => ProgramError::GenericError,
|
_ => ProgramError::GenericError,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn process_vote(&mut self, vote: Vote) {
|
||||||
|
// TODO: Integrity checks
|
||||||
|
// a) Verify the vote's bank hash matches what is expected
|
||||||
|
// b) Verify vote is older than previous votes
|
||||||
|
|
||||||
|
// Only keep around the most recent MAX_VOTE_HISTORY votes
|
||||||
|
if self.votes.len() == MAX_VOTE_HISTORY {
|
||||||
|
self.votes.pop_front();
|
||||||
|
self.credits += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.votes.push_back(vote);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Number of "credits" owed to this account from the mining pool. Submit this
|
||||||
|
/// VoteState to the Rewards program to trade credits for lamports.
|
||||||
|
pub fn credits(&self) -> u64 {
|
||||||
|
self.credits
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clear any credits.
|
||||||
|
pub fn clear_credits(&mut self) {
|
||||||
|
self.credits = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -88,11 +116,24 @@ mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_serde() {
|
fn test_vote_serialize() {
|
||||||
let mut buffer: Vec<u8> = vec![0; get_max_size()];
|
let mut buffer: Vec<u8> = vec![0; get_max_size()];
|
||||||
let mut vote_program = VoteState::default();
|
let mut vote_state = VoteState::default();
|
||||||
vote_program.votes = (0..MAX_VOTE_HISTORY).map(|_| Vote::default()).collect();
|
vote_state.votes.resize(MAX_VOTE_HISTORY, Vote::default());
|
||||||
vote_program.serialize(&mut buffer).unwrap();
|
vote_state.serialize(&mut buffer).unwrap();
|
||||||
assert_eq!(VoteState::deserialize(&buffer).unwrap(), vote_program);
|
assert_eq!(VoteState::deserialize(&buffer).unwrap(), vote_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vote_credits() {
|
||||||
|
let mut vote_state = VoteState::default();
|
||||||
|
vote_state.votes.resize(MAX_VOTE_HISTORY, Vote::default());
|
||||||
|
assert_eq!(vote_state.credits(), 0);
|
||||||
|
vote_state.process_vote(Vote::new(42));
|
||||||
|
assert_eq!(vote_state.credits(), 1);
|
||||||
|
vote_state.process_vote(Vote::new(43));
|
||||||
|
assert_eq!(vote_state.credits(), 2);
|
||||||
|
vote_state.clear_credits();
|
||||||
|
assert_eq!(vote_state.credits(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue