Limit maximum number of shreds in a slot to 32K (#7584)
* Limit maximum number of shreds in a slot to 32K * mark dead slot replay as fatal error
This commit is contained in:
@ -63,6 +63,11 @@ pub const MAX_TURBINE_PROPAGATION_IN_MS: u64 = 100;
|
||||
pub const MAX_TURBINE_DELAY_IN_TICKS: u64 = MAX_TURBINE_PROPAGATION_IN_MS / MS_PER_TICK;
|
||||
const TIMESTAMP_SLOT_RANGE: usize = 5;
|
||||
|
||||
// An upper bound on maximum number of data shreds we can handle in a slot
|
||||
// 32K shreds would allow ~320K peak TPS
|
||||
// (32K shreds per slot * 4 TX per shred * 2.5 slots per sec)
|
||||
pub const MAX_DATA_SHREDS_PER_SLOT: usize = 32_768;
|
||||
|
||||
pub type CompletedSlotsReceiver = Receiver<Vec<u64>>;
|
||||
|
||||
// ledger window
|
||||
@ -1409,6 +1414,9 @@ impl Blocktree {
|
||||
slot: Slot,
|
||||
start_index: u64,
|
||||
) -> Result<(Vec<Entry>, usize, bool)> {
|
||||
if self.is_dead(slot) {
|
||||
return Err(BlocktreeError::DeadSlot);
|
||||
}
|
||||
let slot_meta_cf = self.db.column::<cf::SlotMeta>();
|
||||
let slot_meta = slot_meta_cf.get(slot)?;
|
||||
if slot_meta.is_none() {
|
||||
|
@ -41,6 +41,7 @@ pub enum BlocktreeError {
|
||||
InvalidShredData(Box<bincode::ErrorKind>),
|
||||
RocksDb(#[from] rocksdb::Error),
|
||||
SlotNotRooted,
|
||||
DeadSlot,
|
||||
IO(#[from] std::io::Error),
|
||||
Serialize(#[from] Box<bincode::ErrorKind>),
|
||||
FsExtraError(#[from] fs_extra::error::Error),
|
||||
|
@ -31,6 +31,9 @@ pub const SIZE_OF_COMMON_SHRED_HEADER: usize = 83;
|
||||
pub const SIZE_OF_DATA_SHRED_HEADER: usize = 3;
|
||||
pub const SIZE_OF_CODING_SHRED_HEADER: usize = 6;
|
||||
pub const SIZE_OF_SIGNATURE: usize = 64;
|
||||
pub const SIZE_OF_SHRED_TYPE: usize = 1;
|
||||
pub const SIZE_OF_SHRED_SLOT: usize = 8;
|
||||
pub const SIZE_OF_SHRED_INDEX: usize = 4;
|
||||
pub const SIZE_OF_DATA_SHRED_IGNORED_TAIL: usize =
|
||||
SIZE_OF_COMMON_SHRED_HEADER + SIZE_OF_CODING_SHRED_HEADER;
|
||||
pub const SIZE_OF_DATA_SHRED_PAYLOAD: usize = PACKET_DATA_SIZE
|
||||
@ -38,6 +41,9 @@ 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_SLOT: usize = SIZE_OF_SIGNATURE + SIZE_OF_SHRED_TYPE;
|
||||
pub const OFFSET_OF_SHRED_INDEX: usize = OFFSET_OF_SHRED_SLOT + SIZE_OF_SHRED_SLOT;
|
||||
|
||||
thread_local!(static PAR_THREAD_POOL: RefCell<ThreadPool> = RefCell::new(rayon::ThreadPoolBuilder::new()
|
||||
.num_threads(get_thread_count())
|
||||
.build()
|
||||
@ -924,6 +930,18 @@ pub mod tests {
|
||||
SIZE_OF_SIGNATURE,
|
||||
bincode::serialized_size(&Signature::default()).unwrap() as usize
|
||||
);
|
||||
assert_eq!(
|
||||
SIZE_OF_SHRED_TYPE,
|
||||
bincode::serialized_size(&ShredType::default()).unwrap() as usize
|
||||
);
|
||||
assert_eq!(
|
||||
SIZE_OF_SHRED_SLOT,
|
||||
bincode::serialized_size(&Slot::default()).unwrap() as usize
|
||||
);
|
||||
assert_eq!(
|
||||
SIZE_OF_SHRED_INDEX,
|
||||
bincode::serialized_size(&ShredCommonHeader::default().index).unwrap() as usize
|
||||
);
|
||||
}
|
||||
|
||||
fn verify_test_code_shred(shred: &Shred, index: u32, slot: Slot, pk: &Pubkey, verify: bool) {
|
||||
|
@ -45,6 +45,9 @@ fn verify_shred_cpu(packet: &Packet, slot_leaders: &HashMap<u64, [u8; 32]>) -> O
|
||||
let slot_end = slot_start + size_of::<u64>();
|
||||
let msg_start = sig_end;
|
||||
let msg_end = packet.meta.size;
|
||||
if packet.meta.discard {
|
||||
return Some(0);
|
||||
}
|
||||
trace!("slot start and end {} {}", slot_start, slot_end);
|
||||
if packet.meta.size < slot_end {
|
||||
return Some(0);
|
||||
@ -104,7 +107,7 @@ fn slot_key_data_for_gpu<
|
||||
.map(|packet| {
|
||||
let slot_start = size_of::<Signature>() + size_of::<ShredType>();
|
||||
let slot_end = slot_start + size_of::<u64>();
|
||||
if packet.meta.size < slot_end {
|
||||
if packet.meta.size < slot_end || packet.meta.discard {
|
||||
return std::u64::MAX;
|
||||
}
|
||||
let slot: Option<u64> =
|
||||
|
Reference in New Issue
Block a user