2020-03-30 16:53:25 -07:00
|
|
|
use crate::consensus::VOTE_THRESHOLD_SIZE;
|
|
|
|
use solana_measure::measure::Measure;
|
|
|
|
use solana_metrics::inc_new_counter_info;
|
2019-09-20 19:38:56 -07:00
|
|
|
use solana_runtime::bank::Bank;
|
2019-11-02 00:38:30 -07:00
|
|
|
use solana_sdk::clock::Slot;
|
2019-11-20 10:12:43 -08:00
|
|
|
use solana_vote_program::{vote_state::VoteState, vote_state::MAX_LOCKOUT_HISTORY};
|
2019-11-02 00:38:30 -07:00
|
|
|
use std::{
|
|
|
|
collections::HashMap,
|
|
|
|
sync::atomic::{AtomicBool, Ordering},
|
|
|
|
sync::mpsc::{channel, Receiver, RecvTimeoutError, Sender},
|
|
|
|
sync::{Arc, RwLock},
|
|
|
|
thread::{self, Builder, JoinHandle},
|
|
|
|
time::Duration,
|
|
|
|
};
|
2019-09-04 23:10:25 -07:00
|
|
|
|
2019-10-14 15:24:10 -07:00
|
|
|
#[derive(Clone, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
2019-11-04 15:44:27 -08:00
|
|
|
pub struct BlockCommitment {
|
2020-01-21 19:17:33 -08:00
|
|
|
pub commitment: [u64; MAX_LOCKOUT_HISTORY],
|
2019-09-04 23:10:25 -07:00
|
|
|
}
|
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
impl BlockCommitment {
|
2019-09-20 19:38:56 -07:00
|
|
|
pub fn increase_confirmation_stake(&mut self, confirmation_count: usize, stake: u64) {
|
|
|
|
assert!(confirmation_count > 0 && confirmation_count <= MAX_LOCKOUT_HISTORY);
|
2019-11-04 15:44:27 -08:00
|
|
|
self.commitment[confirmation_count - 1] += stake;
|
2019-09-04 23:10:25 -07:00
|
|
|
}
|
2019-09-20 19:38:56 -07:00
|
|
|
|
|
|
|
pub fn get_confirmation_stake(&mut self, confirmation_count: usize) -> u64 {
|
|
|
|
assert!(confirmation_count > 0 && confirmation_count <= MAX_LOCKOUT_HISTORY);
|
2019-11-04 15:44:27 -08:00
|
|
|
self.commitment[confirmation_count - 1]
|
2019-09-04 23:10:25 -07:00
|
|
|
}
|
2019-10-14 15:24:10 -07:00
|
|
|
#[cfg(test)]
|
2019-11-04 15:44:27 -08:00
|
|
|
pub(crate) fn new(commitment: [u64; MAX_LOCKOUT_HISTORY]) -> Self {
|
|
|
|
Self { commitment }
|
2019-10-14 15:24:10 -07:00
|
|
|
}
|
2019-09-04 23:10:25 -07:00
|
|
|
}
|
|
|
|
|
2020-03-30 10:29:30 -07:00
|
|
|
#[derive(Default)]
|
2019-11-04 15:44:27 -08:00
|
|
|
pub struct BlockCommitmentCache {
|
|
|
|
block_commitment: HashMap<Slot, BlockCommitment>,
|
2019-10-14 15:24:10 -07:00
|
|
|
total_stake: u64,
|
2020-03-30 10:29:30 -07:00
|
|
|
bank: Arc<Bank>,
|
|
|
|
root: Slot,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl std::fmt::Debug for BlockCommitmentCache {
|
|
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
|
|
f.debug_struct("BlockCommitmentCache")
|
|
|
|
.field("block_commitment", &self.block_commitment)
|
|
|
|
.field("total_stake", &self.total_stake)
|
|
|
|
.field(
|
|
|
|
"bank",
|
|
|
|
&format_args!("Bank({{current_slot: {:?}}})", self.bank.slot()),
|
|
|
|
)
|
|
|
|
.field("root", &self.root)
|
|
|
|
.finish()
|
|
|
|
}
|
2019-09-04 23:10:25 -07:00
|
|
|
}
|
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
impl BlockCommitmentCache {
|
2020-03-30 10:29:30 -07:00
|
|
|
pub fn new(
|
|
|
|
block_commitment: HashMap<Slot, BlockCommitment>,
|
|
|
|
total_stake: u64,
|
|
|
|
bank: Arc<Bank>,
|
|
|
|
root: Slot,
|
|
|
|
) -> Self {
|
2019-09-20 19:38:56 -07:00
|
|
|
Self {
|
2019-11-04 15:44:27 -08:00
|
|
|
block_commitment,
|
2019-10-14 15:24:10 -07:00
|
|
|
total_stake,
|
2020-03-30 10:29:30 -07:00
|
|
|
bank,
|
|
|
|
root,
|
2019-09-20 19:38:56 -07:00
|
|
|
}
|
2019-09-04 23:10:25 -07:00
|
|
|
}
|
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
pub fn get_block_commitment(&self, slot: Slot) -> Option<&BlockCommitment> {
|
|
|
|
self.block_commitment.get(&slot)
|
2019-09-04 23:10:25 -07:00
|
|
|
}
|
2019-10-14 15:24:10 -07:00
|
|
|
|
|
|
|
pub fn total_stake(&self) -> u64 {
|
|
|
|
self.total_stake
|
|
|
|
}
|
2019-10-14 22:14:20 -07:00
|
|
|
|
2020-03-30 10:29:30 -07:00
|
|
|
pub fn bank(&self) -> Arc<Bank> {
|
|
|
|
self.bank.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn slot(&self) -> Slot {
|
|
|
|
self.bank.slot()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn root(&self) -> Slot {
|
|
|
|
self.root
|
|
|
|
}
|
|
|
|
|
2020-03-30 16:53:25 -07:00
|
|
|
pub fn get_confirmation_count(&self, slot: Slot) -> Option<usize> {
|
|
|
|
self.get_lockout_count(slot, VOTE_THRESHOLD_SIZE)
|
2019-10-14 22:14:20 -07:00
|
|
|
}
|
|
|
|
|
2020-03-30 16:53:25 -07:00
|
|
|
// Returns the lowest level at which at least `minimum_stake_percentage` of the total epoch
|
|
|
|
// stake is locked out
|
|
|
|
fn get_lockout_count(&self, slot: Slot, minimum_stake_percentage: f64) -> Option<usize> {
|
|
|
|
self.get_block_commitment(slot).map(|block_commitment| {
|
|
|
|
let iterator = block_commitment.commitment.iter().enumerate().rev();
|
|
|
|
let mut sum = 0;
|
|
|
|
for (i, stake) in iterator {
|
|
|
|
sum += stake;
|
|
|
|
if (sum as f64 / self.total_stake as f64) > minimum_stake_percentage {
|
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
0
|
|
|
|
})
|
|
|
|
}
|
|
|
|
#[cfg(test)]
|
|
|
|
pub fn new_for_tests() -> Self {
|
|
|
|
let mut block_commitment: HashMap<Slot, BlockCommitment> = HashMap::new();
|
|
|
|
block_commitment.insert(0, BlockCommitment::default());
|
|
|
|
Self {
|
|
|
|
block_commitment,
|
|
|
|
total_stake: 42,
|
|
|
|
..Self::default()
|
|
|
|
}
|
2019-10-14 22:14:20 -07:00
|
|
|
}
|
2019-09-04 23:10:25 -07:00
|
|
|
}
|
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
pub struct CommitmentAggregationData {
|
2019-09-20 19:38:56 -07:00
|
|
|
bank: Arc<Bank>,
|
2020-03-30 10:29:30 -07:00
|
|
|
root: Slot,
|
2019-09-17 19:43:40 -07:00
|
|
|
total_staked: u64,
|
|
|
|
}
|
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
impl CommitmentAggregationData {
|
2020-03-30 10:29:30 -07:00
|
|
|
pub fn new(bank: Arc<Bank>, root: Slot, total_staked: u64) -> Self {
|
|
|
|
Self {
|
|
|
|
bank,
|
|
|
|
root,
|
|
|
|
total_staked,
|
|
|
|
}
|
2019-09-17 19:43:40 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
pub struct AggregateCommitmentService {
|
|
|
|
t_commitment: JoinHandle<()>,
|
2019-09-17 19:43:40 -07:00
|
|
|
}
|
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
impl AggregateCommitmentService {
|
2019-09-17 19:43:40 -07:00
|
|
|
pub fn new(
|
|
|
|
exit: &Arc<AtomicBool>,
|
2019-11-04 15:44:27 -08:00
|
|
|
block_commitment_cache: Arc<RwLock<BlockCommitmentCache>>,
|
|
|
|
) -> (Sender<CommitmentAggregationData>, Self) {
|
2019-09-20 19:38:56 -07:00
|
|
|
let (sender, receiver): (
|
2019-11-04 15:44:27 -08:00
|
|
|
Sender<CommitmentAggregationData>,
|
|
|
|
Receiver<CommitmentAggregationData>,
|
2019-09-17 19:43:40 -07:00
|
|
|
) = channel();
|
|
|
|
let exit_ = exit.clone();
|
|
|
|
(
|
2019-09-20 19:38:56 -07:00
|
|
|
sender,
|
2019-09-17 19:43:40 -07:00
|
|
|
Self {
|
2019-11-04 15:44:27 -08:00
|
|
|
t_commitment: Builder::new()
|
2019-09-17 19:43:40 -07:00
|
|
|
.name("solana-aggregate-stake-lockouts".to_string())
|
|
|
|
.spawn(move || loop {
|
|
|
|
if exit_.load(Ordering::Relaxed) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2020-01-02 19:50:43 -08:00
|
|
|
if let Err(RecvTimeoutError::Disconnected) =
|
|
|
|
Self::run(&receiver, &block_commitment_cache, &exit_)
|
|
|
|
{
|
|
|
|
break;
|
2019-09-17 19:43:40 -07:00
|
|
|
}
|
|
|
|
})
|
|
|
|
.unwrap(),
|
|
|
|
},
|
|
|
|
)
|
|
|
|
}
|
2019-09-20 19:38:56 -07:00
|
|
|
|
|
|
|
fn run(
|
2019-11-04 15:44:27 -08:00
|
|
|
receiver: &Receiver<CommitmentAggregationData>,
|
|
|
|
block_commitment_cache: &RwLock<BlockCommitmentCache>,
|
2019-09-20 19:38:56 -07:00
|
|
|
exit: &Arc<AtomicBool>,
|
2020-01-02 19:50:43 -08:00
|
|
|
) -> Result<(), RecvTimeoutError> {
|
2019-09-20 19:38:56 -07:00
|
|
|
loop {
|
|
|
|
if exit.load(Ordering::Relaxed) {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
let mut aggregation_data = receiver.recv_timeout(Duration::from_secs(1))?;
|
|
|
|
|
|
|
|
while let Ok(new_data) = receiver.try_recv() {
|
|
|
|
aggregation_data = new_data;
|
|
|
|
}
|
|
|
|
|
|
|
|
let ancestors = aggregation_data.bank.status_cache_ancestors();
|
|
|
|
if ancestors.is_empty() {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-03-30 16:53:25 -07:00
|
|
|
let mut aggregate_commitment_time = Measure::start("aggregate-commitment-ms");
|
2019-11-04 15:44:27 -08:00
|
|
|
let block_commitment = Self::aggregate_commitment(&ancestors, &aggregation_data.bank);
|
2019-09-20 19:38:56 -07:00
|
|
|
|
2020-03-30 10:29:30 -07:00
|
|
|
let mut new_block_commitment = BlockCommitmentCache::new(
|
|
|
|
block_commitment,
|
|
|
|
aggregation_data.total_staked,
|
|
|
|
aggregation_data.bank,
|
|
|
|
aggregation_data.root,
|
|
|
|
);
|
2019-09-20 19:38:56 -07:00
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut w_block_commitment_cache = block_commitment_cache.write().unwrap();
|
2019-09-20 19:38:56 -07:00
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
std::mem::swap(&mut *w_block_commitment_cache, &mut new_block_commitment);
|
2020-03-30 16:53:25 -07:00
|
|
|
aggregate_commitment_time.stop();
|
|
|
|
inc_new_counter_info!(
|
|
|
|
"aggregate-commitment-ms",
|
|
|
|
aggregate_commitment_time.as_ms() as usize
|
|
|
|
);
|
2019-09-20 19:38:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
pub fn aggregate_commitment(ancestors: &[Slot], bank: &Bank) -> HashMap<Slot, BlockCommitment> {
|
2019-09-20 19:38:56 -07:00
|
|
|
assert!(!ancestors.is_empty());
|
|
|
|
|
|
|
|
// Check ancestors is sorted
|
|
|
|
for a in ancestors.windows(2) {
|
|
|
|
assert!(a[0] < a[1]);
|
|
|
|
}
|
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut commitment = HashMap::new();
|
2019-09-20 19:38:56 -07:00
|
|
|
for (_, (lamports, account)) in bank.vote_accounts().into_iter() {
|
|
|
|
if lamports == 0 {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let vote_state = VoteState::from(&account);
|
|
|
|
if vote_state.is_none() {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
let vote_state = vote_state.unwrap();
|
2019-11-04 15:44:27 -08:00
|
|
|
Self::aggregate_commitment_for_vote_account(
|
|
|
|
&mut commitment,
|
2019-09-20 19:38:56 -07:00
|
|
|
&vote_state,
|
|
|
|
ancestors,
|
|
|
|
lamports,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
commitment
|
2019-09-20 19:38:56 -07:00
|
|
|
}
|
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
fn aggregate_commitment_for_vote_account(
|
|
|
|
commitment: &mut HashMap<Slot, BlockCommitment>,
|
2019-09-20 19:38:56 -07:00
|
|
|
vote_state: &VoteState,
|
2019-11-02 00:38:30 -07:00
|
|
|
ancestors: &[Slot],
|
2019-09-20 19:38:56 -07:00
|
|
|
lamports: u64,
|
|
|
|
) {
|
|
|
|
assert!(!ancestors.is_empty());
|
|
|
|
let mut ancestors_index = 0;
|
|
|
|
if let Some(root) = vote_state.root_slot {
|
|
|
|
for (i, a) in ancestors.iter().enumerate() {
|
|
|
|
if *a <= root {
|
2019-11-04 15:44:27 -08:00
|
|
|
commitment
|
2019-09-20 19:38:56 -07:00
|
|
|
.entry(*a)
|
2019-11-04 15:44:27 -08:00
|
|
|
.or_insert_with(BlockCommitment::default)
|
2019-09-20 19:38:56 -07:00
|
|
|
.increase_confirmation_stake(MAX_LOCKOUT_HISTORY, lamports);
|
|
|
|
} else {
|
|
|
|
ancestors_index = i;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for vote in &vote_state.votes {
|
|
|
|
while ancestors[ancestors_index] <= vote.slot {
|
2019-11-04 15:44:27 -08:00
|
|
|
commitment
|
2019-09-20 19:38:56 -07:00
|
|
|
.entry(ancestors[ancestors_index])
|
2019-11-04 15:44:27 -08:00
|
|
|
.or_insert_with(BlockCommitment::default)
|
2019-09-20 19:38:56 -07:00
|
|
|
.increase_confirmation_stake(vote.confirmation_count as usize, lamports);
|
|
|
|
ancestors_index += 1;
|
|
|
|
|
|
|
|
if ancestors_index == ancestors.len() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-09-17 19:43:40 -07:00
|
|
|
|
2019-11-13 10:12:09 -08:00
|
|
|
pub fn join(self) -> thread::Result<()> {
|
2019-11-04 15:44:27 -08:00
|
|
|
self.t_commitment.join()
|
2019-09-17 19:43:40 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-04 23:10:25 -07:00
|
|
|
#[cfg(test)]
|
|
|
|
mod tests {
|
|
|
|
use super::*;
|
2020-03-21 10:54:40 -07:00
|
|
|
use solana_ledger::genesis_utils::{create_genesis_config, GenesisConfigInfo};
|
2019-09-20 19:38:56 -07:00
|
|
|
use solana_sdk::pubkey::Pubkey;
|
2019-11-20 10:12:43 -08:00
|
|
|
use solana_stake_program::stake_state;
|
2020-02-25 17:12:01 -08:00
|
|
|
use solana_vote_program::vote_state::{self, VoteStateVersions};
|
2019-09-04 23:10:25 -07:00
|
|
|
|
|
|
|
#[test]
|
2019-11-04 15:44:27 -08:00
|
|
|
fn test_block_commitment() {
|
|
|
|
let mut cache = BlockCommitment::default();
|
2019-09-20 19:38:56 -07:00
|
|
|
assert_eq!(cache.get_confirmation_stake(1), 0);
|
|
|
|
cache.increase_confirmation_stake(1, 10);
|
|
|
|
assert_eq!(cache.get_confirmation_stake(1), 10);
|
|
|
|
cache.increase_confirmation_stake(1, 20);
|
|
|
|
assert_eq!(cache.get_confirmation_stake(1), 30);
|
|
|
|
}
|
|
|
|
|
2019-10-14 22:14:20 -07:00
|
|
|
#[test]
|
2020-03-30 16:53:25 -07:00
|
|
|
fn test_get_confirmations() {
|
2020-03-30 10:29:30 -07:00
|
|
|
let bank = Arc::new(Bank::default());
|
2019-11-04 15:44:27 -08:00
|
|
|
// Build BlockCommitmentCache with votes at depths 0 and 1 for 2 slots
|
|
|
|
let mut cache0 = BlockCommitment::default();
|
2020-03-30 16:53:25 -07:00
|
|
|
cache0.increase_confirmation_stake(1, 5);
|
|
|
|
cache0.increase_confirmation_stake(2, 40);
|
2019-10-14 22:14:20 -07:00
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut cache1 = BlockCommitment::default();
|
2020-03-30 16:53:25 -07:00
|
|
|
cache1.increase_confirmation_stake(1, 40);
|
|
|
|
cache1.increase_confirmation_stake(2, 5);
|
2019-10-14 22:14:20 -07:00
|
|
|
|
2020-03-30 16:53:25 -07:00
|
|
|
let mut cache2 = BlockCommitment::default();
|
|
|
|
cache2.increase_confirmation_stake(1, 20);
|
|
|
|
cache2.increase_confirmation_stake(2, 5);
|
2019-10-14 22:14:20 -07:00
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut block_commitment = HashMap::new();
|
|
|
|
block_commitment.entry(0).or_insert(cache0.clone());
|
|
|
|
block_commitment.entry(1).or_insert(cache1.clone());
|
2020-03-30 16:53:25 -07:00
|
|
|
block_commitment.entry(2).or_insert(cache2.clone());
|
2020-03-30 10:29:30 -07:00
|
|
|
let block_commitment_cache = BlockCommitmentCache::new(block_commitment, 50, bank, 0);
|
2019-10-14 22:14:20 -07:00
|
|
|
|
2020-03-30 16:53:25 -07:00
|
|
|
assert_eq!(block_commitment_cache.get_confirmation_count(0), Some(2));
|
|
|
|
assert_eq!(block_commitment_cache.get_confirmation_count(1), Some(1));
|
|
|
|
assert_eq!(block_commitment_cache.get_confirmation_count(2), Some(0),);
|
|
|
|
assert_eq!(block_commitment_cache.get_confirmation_count(3), None,);
|
2019-10-14 22:14:20 -07:00
|
|
|
}
|
|
|
|
|
2019-09-20 19:38:56 -07:00
|
|
|
#[test]
|
2019-11-04 15:44:27 -08:00
|
|
|
fn test_aggregate_commitment_for_vote_account_1() {
|
2019-09-20 19:38:56 -07:00
|
|
|
let ancestors = vec![3, 4, 5, 7, 9, 11];
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut commitment = HashMap::new();
|
2019-09-20 19:38:56 -07:00
|
|
|
let lamports = 5;
|
2019-09-25 13:53:49 -07:00
|
|
|
let mut vote_state = VoteState::default();
|
2019-09-20 19:38:56 -07:00
|
|
|
|
|
|
|
let root = ancestors.last().unwrap();
|
|
|
|
vote_state.root_slot = Some(*root);
|
2019-11-04 15:44:27 -08:00
|
|
|
AggregateCommitmentService::aggregate_commitment_for_vote_account(
|
|
|
|
&mut commitment,
|
2019-09-20 19:38:56 -07:00
|
|
|
&vote_state,
|
|
|
|
&ancestors,
|
|
|
|
lamports,
|
2019-09-04 23:10:25 -07:00
|
|
|
);
|
2019-09-20 19:38:56 -07:00
|
|
|
|
|
|
|
for a in ancestors {
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut expected = BlockCommitment::default();
|
2019-09-20 19:38:56 -07:00
|
|
|
expected.increase_confirmation_stake(MAX_LOCKOUT_HISTORY, lamports);
|
2019-11-04 15:44:27 -08:00
|
|
|
assert_eq!(*commitment.get(&a).unwrap(), expected);
|
2019-09-20 19:38:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2019-11-04 15:44:27 -08:00
|
|
|
fn test_aggregate_commitment_for_vote_account_2() {
|
2019-09-20 19:38:56 -07:00
|
|
|
let ancestors = vec![3, 4, 5, 7, 9, 11];
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut commitment = HashMap::new();
|
2019-09-20 19:38:56 -07:00
|
|
|
let lamports = 5;
|
2019-09-25 13:53:49 -07:00
|
|
|
let mut vote_state = VoteState::default();
|
2019-09-20 19:38:56 -07:00
|
|
|
|
|
|
|
let root = ancestors[2];
|
|
|
|
vote_state.root_slot = Some(root);
|
|
|
|
vote_state.process_slot_vote_unchecked(*ancestors.last().unwrap());
|
2019-11-04 15:44:27 -08:00
|
|
|
AggregateCommitmentService::aggregate_commitment_for_vote_account(
|
|
|
|
&mut commitment,
|
2019-09-20 19:38:56 -07:00
|
|
|
&vote_state,
|
|
|
|
&ancestors,
|
|
|
|
lamports,
|
2019-09-04 23:10:25 -07:00
|
|
|
);
|
2019-09-20 19:38:56 -07:00
|
|
|
|
|
|
|
for a in ancestors {
|
|
|
|
if a <= root {
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut expected = BlockCommitment::default();
|
2019-09-20 19:38:56 -07:00
|
|
|
expected.increase_confirmation_stake(MAX_LOCKOUT_HISTORY, lamports);
|
2019-11-04 15:44:27 -08:00
|
|
|
assert_eq!(*commitment.get(&a).unwrap(), expected);
|
2019-09-20 19:38:56 -07:00
|
|
|
} else {
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut expected = BlockCommitment::default();
|
2019-09-20 19:38:56 -07:00
|
|
|
expected.increase_confirmation_stake(1, lamports);
|
2019-11-04 15:44:27 -08:00
|
|
|
assert_eq!(*commitment.get(&a).unwrap(), expected);
|
2019-09-20 19:38:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[test]
|
2019-11-04 15:44:27 -08:00
|
|
|
fn test_aggregate_commitment_for_vote_account_3() {
|
2019-09-20 19:38:56 -07:00
|
|
|
let ancestors = vec![3, 4, 5, 7, 9, 10, 11];
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut commitment = HashMap::new();
|
2019-09-20 19:38:56 -07:00
|
|
|
let lamports = 5;
|
2019-09-25 13:53:49 -07:00
|
|
|
let mut vote_state = VoteState::default();
|
2019-09-20 19:38:56 -07:00
|
|
|
|
|
|
|
let root = ancestors[2];
|
|
|
|
vote_state.root_slot = Some(root);
|
|
|
|
assert!(ancestors[4] + 2 >= ancestors[6]);
|
|
|
|
vote_state.process_slot_vote_unchecked(ancestors[4]);
|
|
|
|
vote_state.process_slot_vote_unchecked(ancestors[6]);
|
2019-11-04 15:44:27 -08:00
|
|
|
AggregateCommitmentService::aggregate_commitment_for_vote_account(
|
|
|
|
&mut commitment,
|
2019-09-20 19:38:56 -07:00
|
|
|
&vote_state,
|
|
|
|
&ancestors,
|
|
|
|
lamports,
|
2019-09-04 23:10:25 -07:00
|
|
|
);
|
2019-09-20 19:38:56 -07:00
|
|
|
|
|
|
|
for (i, a) in ancestors.iter().enumerate() {
|
|
|
|
if *a <= root {
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut expected = BlockCommitment::default();
|
2019-09-20 19:38:56 -07:00
|
|
|
expected.increase_confirmation_stake(MAX_LOCKOUT_HISTORY, lamports);
|
2019-11-04 15:44:27 -08:00
|
|
|
assert_eq!(*commitment.get(&a).unwrap(), expected);
|
2019-09-20 19:38:56 -07:00
|
|
|
} else if i <= 4 {
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut expected = BlockCommitment::default();
|
2019-09-20 19:38:56 -07:00
|
|
|
expected.increase_confirmation_stake(2, lamports);
|
2019-11-04 15:44:27 -08:00
|
|
|
assert_eq!(*commitment.get(&a).unwrap(), expected);
|
2019-09-20 19:38:56 -07:00
|
|
|
} else if i <= 6 {
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut expected = BlockCommitment::default();
|
2019-09-20 19:38:56 -07:00
|
|
|
expected.increase_confirmation_stake(1, lamports);
|
2019-11-04 15:44:27 -08:00
|
|
|
assert_eq!(*commitment.get(&a).unwrap(), expected);
|
2019-09-20 19:38:56 -07:00
|
|
|
}
|
|
|
|
}
|
2019-09-04 23:10:25 -07:00
|
|
|
}
|
2019-09-17 19:43:40 -07:00
|
|
|
|
|
|
|
#[test]
|
2019-11-04 15:44:27 -08:00
|
|
|
fn test_aggregate_commitment_validity() {
|
2019-09-20 19:38:56 -07:00
|
|
|
let ancestors = vec![3, 4, 5, 7, 9, 10, 11];
|
2019-11-08 20:56:57 -08:00
|
|
|
let GenesisConfigInfo {
|
|
|
|
mut genesis_config, ..
|
|
|
|
} = create_genesis_config(10_000);
|
2019-09-20 19:38:56 -07:00
|
|
|
|
2019-09-26 13:29:29 -07:00
|
|
|
let sk1 = Pubkey::new_rand();
|
2019-09-20 19:38:56 -07:00
|
|
|
let pk1 = Pubkey::new_rand();
|
|
|
|
let mut vote_account1 = vote_state::create_account(&pk1, &Pubkey::new_rand(), 0, 100);
|
2019-11-12 12:33:40 -08:00
|
|
|
let stake_account1 =
|
|
|
|
stake_state::create_account(&sk1, &pk1, &vote_account1, &genesis_config.rent, 100);
|
2019-09-26 13:29:29 -07:00
|
|
|
let sk2 = Pubkey::new_rand();
|
2019-09-20 19:38:56 -07:00
|
|
|
let pk2 = Pubkey::new_rand();
|
|
|
|
let mut vote_account2 = vote_state::create_account(&pk2, &Pubkey::new_rand(), 0, 50);
|
2019-11-12 12:33:40 -08:00
|
|
|
let stake_account2 =
|
|
|
|
stake_state::create_account(&sk2, &pk2, &vote_account2, &genesis_config.rent, 50);
|
2019-09-20 19:38:56 -07:00
|
|
|
|
2019-11-08 20:56:57 -08:00
|
|
|
genesis_config.accounts.extend(vec![
|
2019-09-20 19:38:56 -07:00
|
|
|
(pk1, vote_account1.clone()),
|
2019-09-26 13:29:29 -07:00
|
|
|
(sk1, stake_account1),
|
2019-09-20 19:38:56 -07:00
|
|
|
(pk2, vote_account2.clone()),
|
2019-09-26 13:29:29 -07:00
|
|
|
(sk2, stake_account2),
|
2019-09-20 19:38:56 -07:00
|
|
|
]);
|
|
|
|
|
|
|
|
// Create bank
|
2019-11-08 20:56:57 -08:00
|
|
|
let bank = Arc::new(Bank::new(&genesis_config));
|
2019-09-20 19:38:56 -07:00
|
|
|
|
|
|
|
let mut vote_state1 = VoteState::from(&vote_account1).unwrap();
|
|
|
|
vote_state1.process_slot_vote_unchecked(3);
|
|
|
|
vote_state1.process_slot_vote_unchecked(5);
|
2020-02-25 17:12:01 -08:00
|
|
|
let versioned = VoteStateVersions::Current(Box::new(vote_state1));
|
|
|
|
VoteState::to(&versioned, &mut vote_account1).unwrap();
|
2019-09-20 19:38:56 -07:00
|
|
|
bank.store_account(&pk1, &vote_account1);
|
|
|
|
|
|
|
|
let mut vote_state2 = VoteState::from(&vote_account2).unwrap();
|
|
|
|
vote_state2.process_slot_vote_unchecked(9);
|
|
|
|
vote_state2.process_slot_vote_unchecked(10);
|
2020-02-25 17:12:01 -08:00
|
|
|
let versioned = VoteStateVersions::Current(Box::new(vote_state2));
|
|
|
|
VoteState::to(&versioned, &mut vote_account2).unwrap();
|
2019-09-20 19:38:56 -07:00
|
|
|
bank.store_account(&pk2, &vote_account2);
|
|
|
|
|
2019-11-04 15:44:27 -08:00
|
|
|
let commitment = AggregateCommitmentService::aggregate_commitment(&ancestors, &bank);
|
2019-09-20 19:38:56 -07:00
|
|
|
|
|
|
|
for a in ancestors {
|
|
|
|
if a <= 3 {
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut expected = BlockCommitment::default();
|
2019-09-20 19:38:56 -07:00
|
|
|
expected.increase_confirmation_stake(2, 150);
|
2019-11-04 15:44:27 -08:00
|
|
|
assert_eq!(*commitment.get(&a).unwrap(), expected);
|
2019-09-20 19:38:56 -07:00
|
|
|
} else if a <= 5 {
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut expected = BlockCommitment::default();
|
2019-09-20 19:38:56 -07:00
|
|
|
expected.increase_confirmation_stake(1, 100);
|
|
|
|
expected.increase_confirmation_stake(2, 50);
|
2019-11-04 15:44:27 -08:00
|
|
|
assert_eq!(*commitment.get(&a).unwrap(), expected);
|
2019-09-20 19:38:56 -07:00
|
|
|
} else if a <= 9 {
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut expected = BlockCommitment::default();
|
2019-09-20 19:38:56 -07:00
|
|
|
expected.increase_confirmation_stake(2, 50);
|
2019-11-04 15:44:27 -08:00
|
|
|
assert_eq!(*commitment.get(&a).unwrap(), expected);
|
2019-09-20 19:38:56 -07:00
|
|
|
} else if a <= 10 {
|
2019-11-04 15:44:27 -08:00
|
|
|
let mut expected = BlockCommitment::default();
|
2019-09-20 19:38:56 -07:00
|
|
|
expected.increase_confirmation_stake(1, 50);
|
2019-11-04 15:44:27 -08:00
|
|
|
assert_eq!(*commitment.get(&a).unwrap(), expected);
|
2019-09-20 19:38:56 -07:00
|
|
|
} else {
|
2019-11-04 15:44:27 -08:00
|
|
|
assert!(commitment.get(&a).is_none());
|
2019-09-20 19:38:56 -07:00
|
|
|
}
|
|
|
|
}
|
2019-09-17 19:43:40 -07:00
|
|
|
}
|
2019-09-04 23:10:25 -07:00
|
|
|
}
|