Fix bank overlapping another bank's broadcast (#6012)

This commit is contained in:
carllin 2019-09-20 19:37:40 -07:00 committed by GitHub
parent 261b869e27
commit fd6e7020eb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 93 additions and 4 deletions

View File

@ -22,12 +22,12 @@ const RECEIVE_ENTRY_COUNT_THRESHOLD: usize = 8;
pub(super) fn recv_slot_entries(receiver: &Receiver<WorkingBankEntry>) -> Result<ReceiveResults> {
let timer = Duration::new(1, 0);
let (bank, (entry, mut last_tick)) = receiver.recv_timeout(timer)?;
let (mut current_bank, (entry, mut last_tick)) = receiver.recv_timeout(timer)?;
let recv_start = Instant::now();
let mut entries = vec![entry];
let mut slot = bank.slot();
let mut max_tick_height = bank.max_tick_height();
let mut slot = current_bank.slot();
let mut max_tick_height = current_bank.max_tick_height();
assert!(last_tick <= max_tick_height);
@ -39,6 +39,7 @@ pub(super) fn recv_slot_entries(receiver: &Receiver<WorkingBankEntry>) -> Result
entries.clear();
slot = bank.slot();
max_tick_height = bank.max_tick_height();
current_bank = bank;
}
last_tick = tick_height;
entries.push(entry);
@ -58,7 +59,7 @@ pub(super) fn recv_slot_entries(receiver: &Receiver<WorkingBankEntry>) -> Result
Ok(ReceiveResults {
entries,
time_elapsed,
bank,
bank: current_bank,
last_tick,
})
}
@ -96,3 +97,91 @@ pub(super) fn entries_to_shreds(
(shred_infos, u64::from(shredder.index))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::genesis_utils::{create_genesis_block, GenesisBlockInfo};
use solana_sdk::genesis_block::GenesisBlock;
use solana_sdk::pubkey::Pubkey;
use solana_sdk::system_transaction;
use solana_sdk::transaction::Transaction;
use std::sync::mpsc::channel;
fn setup_test() -> (GenesisBlock, Arc<Bank>, Transaction) {
let GenesisBlockInfo {
genesis_block,
mint_keypair,
..
} = create_genesis_block(2);
let bank0 = Arc::new(Bank::new(&genesis_block));
let tx = system_transaction::create_user_account(
&mint_keypair,
&Pubkey::new_rand(),
1,
genesis_block.hash(),
);
(genesis_block, bank0, tx)
}
#[test]
fn test_recv_slot_entries_1() {
let (genesis_block, bank0, tx) = setup_test();
let bank1 = Arc::new(Bank::new_from_parent(&bank0, &Pubkey::default(), 1));
let (s, r) = channel();
let mut last_hash = genesis_block.hash();
assert!(bank1.max_tick_height() > 1);
let entries: Vec<_> = (0..bank1.max_tick_height() + 1)
.map(|i| {
let entry = Entry::new(&last_hash, 1, vec![tx.clone()]);
last_hash = entry.hash;
s.send((bank1.clone(), (entry.clone(), i))).unwrap();
entry
})
.collect();
let result = recv_slot_entries(&r).unwrap();
assert_eq!(result.bank.slot(), bank1.slot());
assert_eq!(result.last_tick, bank1.max_tick_height());
assert_eq!(result.entries, entries);
}
#[test]
fn test_recv_slot_entries_2() {
let (genesis_block, bank0, tx) = setup_test();
let bank1 = Arc::new(Bank::new_from_parent(&bank0, &Pubkey::default(), 1));
let bank2 = Arc::new(Bank::new_from_parent(&bank1, &Pubkey::default(), 2));
let (s, r) = channel();
let mut last_hash = genesis_block.hash();
assert!(bank1.max_tick_height() > 1);
// Simulate slot 2 interrupting slot 1's transmission
let expected_last_index = bank1.max_tick_height() - 1;
let last_entry = (0..bank1.max_tick_height())
.map(|i| {
let entry = Entry::new(&last_hash, 1, vec![tx.clone()]);
last_hash = entry.hash;
// Interrupt slot 1 right before the last tick
if i == expected_last_index {
s.send((bank2.clone(), (entry.clone(), i))).unwrap();
Some(entry)
} else {
s.send((bank1.clone(), (entry, i))).unwrap();
None
}
})
.last()
.unwrap()
.unwrap();
let result = recv_slot_entries(&r).unwrap();
assert_eq!(result.bank.slot(), bank2.slot());
assert_eq!(result.last_tick, expected_last_index);
assert_eq!(result.entries, vec![last_entry]);
}
}