switch vote program to use slot height instead of tick height, change confirmation computation to use slots
This commit is contained in:
@ -27,13 +27,13 @@ pub const MAX_VOTE_HISTORY: usize = 32;
|
||||
#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone)]
|
||||
pub struct Vote {
|
||||
// TODO: add signature of the state here as well
|
||||
/// A vote for height tick_height
|
||||
pub tick_height: u64,
|
||||
/// A vote for height slot_height
|
||||
pub slot_height: u64,
|
||||
}
|
||||
|
||||
impl Vote {
|
||||
pub fn new(tick_height: u64) -> Self {
|
||||
Self { tick_height }
|
||||
pub fn new(slot_height: u64) -> Self {
|
||||
Self { slot_height }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,11 +14,11 @@ pub struct VoteTransaction {}
|
||||
impl VoteTransaction {
|
||||
pub fn new_vote<T: KeypairUtil>(
|
||||
voting_keypair: &T,
|
||||
tick_height: u64,
|
||||
slot_height: u64,
|
||||
last_id: Hash,
|
||||
fee: u64,
|
||||
) -> Transaction {
|
||||
let vote = Vote { tick_height };
|
||||
let vote = Vote { slot_height };
|
||||
let instruction = VoteInstruction::Vote(vote);
|
||||
Transaction::new(
|
||||
voting_keypair,
|
||||
@ -81,12 +81,12 @@ mod tests {
|
||||
#[test]
|
||||
fn test_get_votes() {
|
||||
let keypair = Keypair::new();
|
||||
let tick_height = 1;
|
||||
let slot_height = 1;
|
||||
let last_id = Hash::default();
|
||||
let transaction = VoteTransaction::new_vote(&keypair, tick_height, last_id, 0);
|
||||
let transaction = VoteTransaction::new_vote(&keypair, slot_height, last_id, 0);
|
||||
assert_eq!(
|
||||
VoteTransaction::get_votes(&transaction),
|
||||
vec![(keypair.pubkey(), Vote::new(tick_height), last_id)]
|
||||
vec![(keypair.pubkey(), Vote::new(slot_height), last_id)]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ fn is_active_staker(vote_state: &VoteState, lower_bound: u64, upper_bound: u64)
|
||||
vote_state
|
||||
.votes
|
||||
.back()
|
||||
.filter(|vote| vote.tick_height >= lower_bound && vote.tick_height <= upper_bound)
|
||||
.filter(|vote| vote.slot_height >= lower_bound && vote.slot_height <= upper_bound)
|
||||
.is_some()
|
||||
}
|
||||
|
||||
@ -36,8 +36,8 @@ pub struct ActiveStakers {
|
||||
}
|
||||
|
||||
impl ActiveStakers {
|
||||
pub fn new_with_bounds(bank: &Bank, active_window_tick_length: u64, upper_bound: u64) -> Self {
|
||||
let lower_bound = upper_bound.saturating_sub(active_window_tick_length);
|
||||
pub fn new_with_bounds(bank: &Bank, active_window_num_slots: u64, upper_bound: u64) -> Self {
|
||||
let lower_bound = upper_bound.saturating_sub(active_window_num_slots);
|
||||
let mut stakes: Vec<_> = bank
|
||||
.vote_states(|vote_state| is_active_staker(vote_state, lower_bound, upper_bound))
|
||||
.iter()
|
||||
@ -96,9 +96,9 @@ pub mod tests {
|
||||
bank.process_transaction(&tx).unwrap();
|
||||
}
|
||||
|
||||
pub fn push_vote<T: KeypairUtil>(voting_keypair: &T, bank: &Bank, tick_height: u64) {
|
||||
pub fn push_vote<T: KeypairUtil>(voting_keypair: &T, bank: &Bank, slot_height: u64) {
|
||||
let last_id = bank.last_id();
|
||||
let tx = VoteTransaction::new_vote(voting_keypair, tick_height, last_id, 0);
|
||||
let tx = VoteTransaction::new_vote(voting_keypair, slot_height, last_id, 0);
|
||||
bank.process_transaction(&tx).unwrap();
|
||||
}
|
||||
|
||||
@ -107,10 +107,10 @@ pub mod tests {
|
||||
voting_keypair: &T,
|
||||
bank: &Bank,
|
||||
num_tokens: u64,
|
||||
tick_height: u64,
|
||||
slot_height: u64,
|
||||
) {
|
||||
new_vote_account(from_keypair, &voting_keypair.pubkey(), bank, num_tokens);
|
||||
push_vote(voting_keypair, bank, tick_height);
|
||||
push_vote(voting_keypair, bank, slot_height);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -154,8 +154,8 @@ pub mod tests {
|
||||
.unwrap();
|
||||
|
||||
// Create a vote account and push a vote
|
||||
let tick_height = start_height + active_window_tick_length + 1;
|
||||
new_vote_account_with_vote(&new_keypair, &Keypair::new(), &bank, 1, tick_height);
|
||||
let slot_height = start_height + active_window_tick_length + 1;
|
||||
new_vote_account_with_vote(&new_keypair, &Keypair::new(), &bank, 1, slot_height);
|
||||
}
|
||||
new_ids.sort();
|
||||
|
||||
@ -273,7 +273,7 @@ pub mod tests {
|
||||
assert_eq!(result.len(), 0);
|
||||
}
|
||||
|
||||
// Vote at tick_height 2
|
||||
// Vote at slot_height 2
|
||||
push_vote(&voting_keypair, &bank, 2);
|
||||
|
||||
{
|
||||
|
@ -59,6 +59,7 @@ impl BankingStage {
|
||||
max_tick_height,
|
||||
};
|
||||
|
||||
let ticks_per_slot = max_tick_height - bank.tick_height();
|
||||
let poh_recorder = PohRecorder::new(bank.tick_height(), *last_entry_id);
|
||||
|
||||
// Single thread to generate entries from many banks.
|
||||
@ -74,8 +75,12 @@ impl BankingStage {
|
||||
.expect("failed to send leader to poh_service");
|
||||
|
||||
// Single thread to compute confirmation
|
||||
let leader_confirmation_service =
|
||||
LeaderConfirmationService::new(bank.clone(), leader_id, poh_exit.clone());
|
||||
let leader_confirmation_service = LeaderConfirmationService::new(
|
||||
bank.clone(),
|
||||
leader_id,
|
||||
poh_exit.clone(),
|
||||
ticks_per_slot,
|
||||
);
|
||||
|
||||
// Many banks that process transactions in parallel.
|
||||
let bank_thread_hdls: Vec<JoinHandle<UnprocessedPackets>> = (0..Self::num_threads())
|
||||
|
@ -30,6 +30,7 @@ impl LeaderConfirmationService {
|
||||
bank: &Arc<Bank>,
|
||||
leader_id: Pubkey,
|
||||
last_valid_validator_timestamp: u64,
|
||||
ticks_per_slot: u64,
|
||||
) -> result::Result<u64, ConfirmationError> {
|
||||
let mut total_stake = 0;
|
||||
|
||||
@ -47,7 +48,8 @@ impl LeaderConfirmationService {
|
||||
vote_state
|
||||
.votes
|
||||
.back()
|
||||
.map(|vote| (vote.tick_height, validator_stake))
|
||||
// A vote for a slot is like a vote for the last tick in that slot
|
||||
.map(|vote| ((vote.slot_height + 1) * ticks_per_slot - 1, validator_stake))
|
||||
})
|
||||
.collect();
|
||||
|
||||
@ -78,10 +80,14 @@ impl LeaderConfirmationService {
|
||||
bank: &Arc<Bank>,
|
||||
leader_id: Pubkey,
|
||||
last_valid_validator_timestamp: &mut u64,
|
||||
ticks_per_slot: u64,
|
||||
) {
|
||||
if let Ok(super_majority_timestamp) =
|
||||
Self::get_last_supermajority_timestamp(bank, leader_id, *last_valid_validator_timestamp)
|
||||
{
|
||||
if let Ok(super_majority_timestamp) = Self::get_last_supermajority_timestamp(
|
||||
bank,
|
||||
leader_id,
|
||||
*last_valid_validator_timestamp,
|
||||
ticks_per_slot,
|
||||
) {
|
||||
let now = timing::timestamp();
|
||||
let confirmation_ms = now - super_majority_timestamp;
|
||||
|
||||
@ -99,9 +105,14 @@ impl LeaderConfirmationService {
|
||||
}
|
||||
|
||||
/// Create a new LeaderConfirmationService for computing confirmation.
|
||||
pub fn new(bank: Arc<Bank>, leader_id: Pubkey, exit: Arc<AtomicBool>) -> Self {
|
||||
pub fn new(
|
||||
bank: Arc<Bank>,
|
||||
leader_id: Pubkey,
|
||||
exit: Arc<AtomicBool>,
|
||||
ticks_per_slot: u64,
|
||||
) -> Self {
|
||||
let thread_hdl = Builder::new()
|
||||
.name("solana-leader-confirmation-stage".to_string())
|
||||
.name("solana-leader-confirmation-service".to_string())
|
||||
.spawn(move || {
|
||||
let mut last_valid_validator_timestamp = 0;
|
||||
loop {
|
||||
@ -112,6 +123,7 @@ impl LeaderConfirmationService {
|
||||
&bank,
|
||||
leader_id,
|
||||
&mut last_valid_validator_timestamp,
|
||||
ticks_per_slot,
|
||||
);
|
||||
sleep(Duration::from_millis(COMPUTE_CONFIRMATION_MS));
|
||||
}
|
||||
@ -189,6 +201,7 @@ pub mod tests {
|
||||
&bank,
|
||||
genesis_block.bootstrap_leader_id,
|
||||
&mut last_confirmation_time,
|
||||
1,
|
||||
);
|
||||
|
||||
// Get another validator to vote, so we now have 2/3 consensus
|
||||
@ -200,6 +213,7 @@ pub mod tests {
|
||||
&bank,
|
||||
genesis_block.bootstrap_leader_id,
|
||||
&mut last_confirmation_time,
|
||||
1,
|
||||
);
|
||||
assert!(last_confirmation_time > 0);
|
||||
}
|
||||
|
Reference in New Issue
Block a user