Distinguish between shred type in shred fetch stage duplicate filter (#10068)

* Shred type check

* Test
This commit is contained in:
sakridge 2020-05-15 13:23:56 -07:00 committed by GitHub
parent c4a096d8d4
commit f562ed4cc8
2 changed files with 69 additions and 13 deletions

View File

@ -4,7 +4,8 @@ use bv::BitVec;
use solana_ledger::bank_forks::BankForks;
use solana_ledger::blockstore::MAX_DATA_SHREDS_PER_SLOT;
use solana_ledger::shred::{
OFFSET_OF_SHRED_INDEX, OFFSET_OF_SHRED_SLOT, SIZE_OF_SHRED_INDEX, SIZE_OF_SHRED_SLOT,
CODING_SHRED, DATA_SHRED, OFFSET_OF_SHRED_INDEX, OFFSET_OF_SHRED_SLOT, OFFSET_OF_SHRED_TYPE,
SIZE_OF_SHRED_INDEX, SIZE_OF_SHRED_SLOT,
};
use solana_perf::cuda_runtime::PinnedVec;
use solana_perf::packet::{limited_deserialize, Packet, PacketsRecycler};
@ -20,7 +21,7 @@ use std::sync::RwLock;
use std::thread::{self, Builder, JoinHandle};
use std::time::Instant;
pub type ShredsReceived = HashMap<Slot, BitVec<u64>>;
pub type ShredsReceived = HashMap<(Slot, u8), BitVec<u64>>;
#[derive(Default)]
struct ShredFetchStats {
@ -78,17 +79,26 @@ impl ShredFetchStage {
p.meta.discard = true;
if let Some((slot, index)) = Self::get_slot_index(p, stats) {
// Seems reasonable to limit shreds to 2 epochs away
if slot > last_root && slot < (last_slot + 2 * slots_per_epoch) {
// Shred filter
let slot_received = shreds_received
.entry(slot)
.or_insert_with(|| BitVec::new_fill(false, MAX_DATA_SHREDS_PER_SLOT as u64));
if !slot_received.get(index.into()) {
p.meta.discard = false;
modify(p);
slot_received.set(index.into(), true);
} else {
stats.duplicate_shred += 1;
if slot > last_root
&& slot < (last_slot + 2 * slots_per_epoch)
&& p.meta.size > OFFSET_OF_SHRED_TYPE
{
let shred_type = p.data[OFFSET_OF_SHRED_TYPE];
if shred_type == DATA_SHRED || shred_type == CODING_SHRED {
// Shred filter
let slot_received =
shreds_received
.entry((slot, shred_type))
.or_insert_with(|| {
BitVec::new_fill(false, MAX_DATA_SHREDS_PER_SLOT as u64)
});
if !slot_received.get(index.into()) {
p.meta.discard = false;
modify(p);
slot_received.set(index.into(), true);
} else {
stats.duplicate_shred += 1;
}
}
} else {
stats.slot_out_of_range += 1;
@ -258,6 +268,51 @@ mod tests {
use super::*;
use solana_ledger::shred::Shred;
#[test]
fn test_data_code_same_index() {
solana_logger::setup();
let mut shreds_received = ShredsReceived::default();
let mut packet = Packet::default();
let mut stats = ShredFetchStats::default();
let slot = 1;
let shred = Shred::new_from_data(slot, 3, 0, None, true, true, 0, 0, 0);
shred.copy_to_packet(&mut packet);
let last_root = 0;
let last_slot = 100;
let slots_per_epoch = 10;
ShredFetchStage::process_packet(
&mut packet,
&mut shreds_received,
&mut stats,
last_root,
last_slot,
slots_per_epoch,
&|_p| {},
);
assert!(!packet.meta.discard);
let coding = solana_ledger::shred::Shredder::generate_coding_shreds(
slot,
1.0f32,
&[shred],
10,
false,
);
coding[0].copy_to_packet(&mut packet);
ShredFetchStage::process_packet(
&mut packet,
&mut shreds_received,
&mut stats,
last_root,
last_slot,
slots_per_epoch,
&|_p| {},
);
assert!(!packet.meta.discard);
}
#[test]
fn test_shred_filter() {
solana_logger::setup();

View File

@ -41,6 +41,7 @@ pub const SIZE_OF_DATA_SHRED_PAYLOAD: usize = PACKET_DATA_SIZE
- SIZE_OF_DATA_SHRED_HEADER
- SIZE_OF_DATA_SHRED_IGNORED_TAIL;
pub const OFFSET_OF_SHRED_TYPE: usize = SIZE_OF_SIGNATURE;
pub const OFFSET_OF_SHRED_SLOT: usize = SIZE_OF_SIGNATURE + SIZE_OF_SHRED_TYPE;
pub const OFFSET_OF_SHRED_INDEX: usize = OFFSET_OF_SHRED_SLOT + SIZE_OF_SHRED_SLOT;