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