Implement locktower voting (#3251)

* locktower components and tests

* integrate locktower into replay stage

* track locktower duration

* make sure threshold is checked after simulating the vote

* check vote lockouts using the VoteState program

* duplicate vote test

* epoch stakes

* disable impossible to verify tests
This commit is contained in:
anatoly yakovenko
2019-03-18 12:12:33 -07:00
committed by GitHub
parent cedff2fca1
commit 61a4b998fa
7 changed files with 735 additions and 54 deletions

View File

@@ -1,7 +1,7 @@
//! The `bank_forks` module implments BankForks a DAG of checkpointed Banks
use hashbrown::{HashMap, HashSet};
use solana_runtime::bank::Bank;
use std::collections::HashMap;
use std::ops::Index;
use std::sync::Arc;
@@ -27,6 +27,47 @@ impl BankForks {
working_bank,
}
}
/// Create a map of bank slot id to the set of ancestors for the bank slot.
pub fn ancestors(&self) -> HashMap<u64, HashSet<u64>> {
let mut ancestors = HashMap::new();
let mut pending: Vec<Arc<Bank>> = self.banks.values().cloned().collect();
while !pending.is_empty() {
let bank = pending.pop().unwrap();
if ancestors.get(&bank.slot()).is_some() {
continue;
}
let set = bank.parents().into_iter().map(|b| b.slot()).collect();
ancestors.insert(bank.slot(), set);
pending.extend(bank.parents().into_iter());
}
ancestors
}
/// Create a map of bank slot id to the set of all of its descendants
pub fn decendants(&self) -> HashMap<u64, HashSet<u64>> {
let mut decendants = HashMap::new();
let mut pending: Vec<Arc<Bank>> = self.banks.values().cloned().collect();
let mut done = HashSet::new();
assert!(!pending.is_empty());
while !pending.is_empty() {
let bank = pending.pop().unwrap();
if done.contains(&bank.slot()) {
continue;
}
done.insert(bank.slot());
let _ = decendants.entry(bank.slot()).or_insert(HashSet::new());
for parent in bank.parents() {
decendants
.entry(parent.slot())
.or_insert(HashSet::new())
.insert(bank.slot());
}
pending.extend(bank.parents().into_iter());
}
decendants
}
pub fn frozen_banks(&self) -> HashMap<u64, Arc<Bank>> {
let mut frozen_banks: Vec<Arc<Bank>> = vec![];
frozen_banks.extend(self.banks.values().filter(|v| v.is_frozen()).cloned());
@@ -106,6 +147,41 @@ mod tests {
assert_eq!(bank_forks.working_bank().tick_height(), 1);
}
#[test]
fn test_bank_forks_decendants() {
let (genesis_block, _) = GenesisBlock::new(10_000);
let bank = Bank::new(&genesis_block);
let mut bank_forks = BankForks::new(0, bank);
let bank0 = bank_forks[0].clone();
let bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
bank_forks.insert(1, bank);
let bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 2);
bank_forks.insert(2, bank);
let decendants = bank_forks.decendants();
let children: Vec<u64> = decendants[&0].iter().cloned().collect();
assert_eq!(children, vec![1, 2]);
assert!(decendants[&1].is_empty());
assert!(decendants[&2].is_empty());
}
#[test]
fn test_bank_forks_ancestors() {
let (genesis_block, _) = GenesisBlock::new(10_000);
let bank = Bank::new(&genesis_block);
let mut bank_forks = BankForks::new(0, bank);
let bank0 = bank_forks[0].clone();
let bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 1);
bank_forks.insert(1, bank);
let bank = Bank::new_from_parent(&bank0, &Pubkey::default(), 2);
bank_forks.insert(2, bank);
let ancestors = bank_forks.ancestors();
assert!(ancestors[&0].is_empty());
let parents: Vec<u64> = ancestors[&1].iter().cloned().collect();
assert_eq!(parents, vec![0]);
let parents: Vec<u64> = ancestors[&2].iter().cloned().collect();
assert_eq!(parents, vec![0]);
}
#[test]
fn test_bank_forks_frozen_banks() {
let (genesis_block, _) = GenesisBlock::new(10_000);