Add test to ensure data shreds with empty data would be inserted (#16955)

* Add test to ensure data shreds with empty data would be inserted

* Add error log statements for malformed shreds
This commit is contained in:
steviez 2021-04-30 10:38:15 -05:00 committed by GitHub
parent c4943f3cb0
commit 475b00c42f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 88 additions and 33 deletions

View File

@ -1292,9 +1292,37 @@ impl Blockstore {
};
if shred.data_header.size == 0 {
let leader_pubkey = leader_schedule
.and_then(|leader_schedule| leader_schedule.slot_leader_at(slot, None));
datapoint_error!(
"blockstore_error",
(
"error",
format!(
"Leader {:?}, slot {}: received index {} is empty",
leader_pubkey, slot, shred_index,
),
String
)
);
return false;
}
if shred.payload.len() > SHRED_PAYLOAD_SIZE {
let leader_pubkey = leader_schedule
.and_then(|leader_schedule| leader_schedule.slot_leader_at(slot, None));
datapoint_error!(
"blockstore_error",
(
"error",
format!(
"Leader {:?}, slot {}: received index {} shred.payload.len() > SHRED_PAYLOAD_SIZE",
leader_pubkey, slot, shred_index,
),
String
)
);
return false;
}
@ -1303,8 +1331,7 @@ impl Blockstore {
let last_index = slot_meta.last_index;
if shred_index >= last_index {
let leader_pubkey = leader_schedule
.map(|leader_schedule| leader_schedule.slot_leader_at(slot, None))
.unwrap_or(None);
.and_then(|leader_schedule| leader_schedule.slot_leader_at(slot, None));
let ending_shred: Cow<Vec<u8>> = self.get_data_shred_from_just_inserted_or_db(
just_inserted_data_shreds,
@ -1324,24 +1351,23 @@ impl Blockstore {
}
datapoint_error!(
"blockstore_error",
(
"error",
format!(
"Leader {:?}, slot {}: received index {} >= slot.last_index {}, is_recovered: {}",
leader_pubkey, slot, shred_index, last_index, is_recovered
),
String
)
);
"blockstore_error",
(
"error",
format!(
"Leader {:?}, slot {}: received index {} >= slot.last_index {}, is_recovered: {}",
leader_pubkey, slot, shred_index, last_index, is_recovered
),
String
)
);
return false;
}
// Check that we do not receive a shred with "last_index" true, but shred_index
// less than our current received
if last_in_slot && shred_index < slot_meta.received {
let leader_pubkey = leader_schedule
.map(|leader_schedule| leader_schedule.slot_leader_at(slot, None))
.unwrap_or(None);
.and_then(|leader_schedule| leader_schedule.slot_leader_at(slot, None));
let ending_shred: Cow<Vec<u8>> = self.get_data_shred_from_just_inserted_or_db(
just_inserted_data_shreds,
@ -1361,16 +1387,16 @@ impl Blockstore {
}
datapoint_error!(
"blockstore_error",
(
"error",
format!(
"Leader {:?}, slot {}: received shred_index {} < slot.received {}, is_recovered: {}",
leader_pubkey, slot, shred_index, slot_meta.received, is_recovered
),
String
)
);
"blockstore_error",
(
"error",
format!(
"Leader {:?}, slot {}: received shred_index {} < slot.received {}, is_recovered: {}",
leader_pubkey, slot, shred_index, slot_meta.received, is_recovered
),
String
)
);
return false;
}
@ -5303,17 +5329,46 @@ pub mod tests {
let mut shred5 = shreds[5].clone();
shred5.payload.push(10);
shred5.data_header.size = shred5.payload.len() as u16;
assert_eq!(
blockstore.should_insert_data_shred(
&shred5,
&slot_meta,
&HashMap::new(),
&last_root,
None,
false
),
assert!(!blockstore.should_insert_data_shred(
&shred5,
&slot_meta,
&HashMap::new(),
&last_root,
None,
false
));
// Ensure that an empty shred (one with no data) would get inserted. Such shreds
// may be used as signals (broadcast does so to indicate a slot was interrupted)
// Reuse shred5's header values to avoid a false negative result
let mut empty_shred = Shred::new_from_data(
shred5.common_header.slot,
shred5.common_header.index,
shred5.data_header.parent_offset,
None, // data
true, // is_last_data
true, // is_last_in_slot
0, // reference_tick
shred5.common_header.version,
shred5.common_header.fec_set_index,
);
assert!(blockstore.should_insert_data_shred(
&empty_shred,
&slot_meta,
&HashMap::new(),
&last_root,
None,
false
));
empty_shred.data_header.size = 0;
assert!(!blockstore.should_insert_data_shred(
&empty_shred,
&slot_meta,
&HashMap::new(),
&last_root,
None,
false
));
// Trying to insert another "is_last" shred with index < the received index should fail
// skip over shred 7