filter invalid repair requests by size (#30951)

This commit is contained in:
Jeff Biseda 2023-04-28 16:57:15 -07:00 committed by GitHub
parent aa7baaff29
commit b5bb5c6da1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 112 additions and 4 deletions

View File

@ -258,6 +258,25 @@ pub enum RepairProtocol {
},
}
const REPAIR_REQUEST_PONG_SERIALIZED_BYTES: usize = PUBKEY_BYTES + HASH_BYTES + SIGNATURE_BYTES;
const REPAIR_REQUEST_MIN_BYTES: usize = REPAIR_REQUEST_PONG_SERIALIZED_BYTES;
fn discard_malformed_repair_requests(
batch: &mut PacketBatch,
stats: &mut ServeRepairStats,
) -> usize {
let mut well_formed_requests = 0;
for packet in batch.iter_mut() {
if packet.meta().size < REPAIR_REQUEST_MIN_BYTES {
stats.err_malformed += 1;
packet.meta_mut().set_discard(true);
} else {
well_formed_requests += 1;
}
}
well_formed_requests
}
#[derive(Debug, AbiEnumVisitor, AbiExample, Deserialize, Serialize)]
#[frozen_abi(digest = "CkffjyMPCwuJgk9NiCMELXLCecAnTPZqpKEnUCb3VyVf")]
pub(crate) enum RepairResponse {
@ -603,7 +622,12 @@ impl ServeRepair {
}
result.ok()
};
reqs_v.iter().flatten().filter_map(decode_packet).collect()
reqs_v
.iter()
.flatten()
.filter(|packet| !packet.meta().discard())
.filter_map(decode_packet)
.collect()
}
/// Process messages from the network
@ -637,12 +661,20 @@ impl ServeRepair {
};
let mut dropped_requests = 0;
while let Ok(more) = requests_receiver.try_recv() {
let mut well_formed_requests = discard_malformed_repair_requests(&mut reqs_v[0], stats);
for mut more in requests_receiver.try_iter() {
total_requests += more.len();
if total_requests > max_buffered_packets {
if well_formed_requests > max_buffered_packets {
// Already exceeded max. Don't waste time discarding
dropped_requests += more.len();
} else {
continue;
}
let retained = discard_malformed_repair_requests(&mut more, stats);
well_formed_requests += retained;
if retained > 0 && well_formed_requests <= max_buffered_packets {
reqs_v.push(more);
} else {
dropped_requests += more.len();
}
}
@ -1402,6 +1434,82 @@ mod tests {
}
}
fn repair_request_header_for_tests() -> RepairRequestHeader {
RepairRequestHeader {
signature: Signature::default(),
sender: Pubkey::default(),
recipient: Pubkey::default(),
timestamp: timestamp(),
nonce: Nonce::default(),
}
}
#[test]
fn test_check_well_formed_repair_request() {
let mut rng = rand::thread_rng();
let keypair = Keypair::new();
let ping = ping_pong::Ping::<[u8; 32]>::new_rand(&mut rng, &keypair).unwrap();
let pong = Pong::new(&ping, &keypair).unwrap();
let request = RepairProtocol::Pong(pong);
let mut pkt = Packet::from_data(None, &request).unwrap();
let mut batch = PacketBatch::new(vec![pkt.clone()]);
let mut stats = ServeRepairStats::default();
let num_well_formed = discard_malformed_repair_requests(&mut batch, &mut stats);
assert_eq!(num_well_formed, 1);
pkt.meta_mut().size = 5;
let mut batch = PacketBatch::new(vec![pkt]);
let mut stats = ServeRepairStats::default();
let num_well_formed = discard_malformed_repair_requests(&mut batch, &mut stats);
assert_eq!(num_well_formed, 0);
assert_eq!(stats.err_malformed, 1);
let request = RepairProtocol::WindowIndex {
header: repair_request_header_for_tests(),
slot: 123,
shred_index: 456,
};
let mut pkt = Packet::from_data(None, &request).unwrap();
let mut batch = PacketBatch::new(vec![pkt.clone()]);
let mut stats = ServeRepairStats::default();
let num_well_formed = discard_malformed_repair_requests(&mut batch, &mut stats);
assert_eq!(num_well_formed, 1);
pkt.meta_mut().size = 8;
let mut batch = PacketBatch::new(vec![pkt]);
let mut stats = ServeRepairStats::default();
let num_well_formed = discard_malformed_repair_requests(&mut batch, &mut stats);
assert_eq!(num_well_formed, 0);
assert_eq!(stats.err_malformed, 1);
let request = RepairProtocol::AncestorHashes {
header: repair_request_header_for_tests(),
slot: 123,
};
let mut pkt = Packet::from_data(None, &request).unwrap();
let mut batch = PacketBatch::new(vec![pkt.clone()]);
let mut stats = ServeRepairStats::default();
let num_well_formed = discard_malformed_repair_requests(&mut batch, &mut stats);
assert_eq!(num_well_formed, 1);
pkt.meta_mut().size = 1;
let mut batch = PacketBatch::new(vec![pkt]);
let mut stats = ServeRepairStats::default();
let num_well_formed = discard_malformed_repair_requests(&mut batch, &mut stats);
assert_eq!(num_well_formed, 0);
assert_eq!(stats.err_malformed, 1);
let request = RepairProtocol::LegacyOrphan(LegacyContactInfo::default(), 123);
let mut pkt = Packet::from_data(None, &request).unwrap();
let mut batch = PacketBatch::new(vec![pkt.clone()]);
let mut stats = ServeRepairStats::default();
let num_well_formed = discard_malformed_repair_requests(&mut batch, &mut stats);
assert_eq!(num_well_formed, 1);
pkt.meta_mut().size = 3;
let mut batch = PacketBatch::new(vec![pkt]);
let mut stats = ServeRepairStats::default();
let num_well_formed = discard_malformed_repair_requests(&mut batch, &mut stats);
assert_eq!(num_well_formed, 0);
assert_eq!(stats.err_malformed, 1);
}
#[test]
fn test_serialize_deserialize_signed_request() {
let GenesisConfigInfo { genesis_config, .. } = create_genesis_config(10_000);