infinite loops in check_orphans, if block in orphans has a forked parent (#1452)

* fix: if block in orphans queue has a forked parent, cause infinite loop in check_orphans()
* process all orphans at a given height before go to next height
This commit is contained in:
Gary Yu 2018-09-02 03:09:38 +08:00 committed by Ignotus Peverell
parent 8a39f1fc75
commit f971e8de77

View file

@ -350,42 +350,60 @@ impl Chain {
/// Check for orphans, once a block is successfully added
pub fn check_orphans(&self, mut height: u64) {
let initial_height = height;
// Is there an orphan in our orphans that we can now process?
loop {
trace!(
LOGGER,
"chain: doing check_orphans at {}, # orphans {}",
"check_orphans: at {}, # orphans {}",
height,
self.orphans.len(),
);
// Is there an orphan in our orphans that we can now process?
loop {
let mut orphan_accepted = false;
let mut height_accepted = height;
if let Some(orphans) = self.orphans.remove_by_height(&height) {
for orphan in orphans {
trace!(
let orphans_len = orphans.len();
for (i, orphan) in orphans.into_iter().enumerate() {
debug!(
LOGGER,
"chain: got block {} at {} from orphans. # orphans remaining {}",
"check_orphans: get block {} at {}{}",
orphan.block.hash(),
height,
self.orphans.len(),
if orphans_len > 1 {
format!(", no.{} of {} orphans", i, orphans_len)
} else {
String::new()
},
);
let res = self.process_block_no_orphans(orphan.block, orphan.opts);
if let Ok((_, Some(b))) = res {
orphan_accepted = true;
height_accepted = b.header.height;
}
}
if orphan_accepted {
// We accepted a block, so see if we can accept any orphans
height = b.header.height + 1;
} else {
height = height_accepted + 1;
continue;
}
}
break;
}
}
} else {
break;
}
}
trace!(
if initial_height != height {
debug!(
LOGGER,
"chain: done check_orphans at {}. # remaining orphans {}",
height - 1,
"check_orphans: {} blocks accepted since height {}, remaining # orphans {}",
height - initial_height,
initial_height,
self.orphans.len(),
);
}
}
/// For the given commitment find the unspent output and return the
/// associated Return an error if the output does not exist or has been