Master port #605 (#606)

* port of stack overflow fix from testnet to master
* update process_block to encapsulate orphan check workflow
This commit is contained in:
Yeastplume 2018-01-24 18:20:34 +00:00 committed by Ignotus Peverell
parent 8710d52797
commit 2def215553
2 changed files with 53 additions and 16 deletions

View file

@ -194,12 +194,31 @@ impl Chain {
pow_verifier: pow_verifier,
})
}
/// Processes a single block, then checks for orphans, processing
/// those as well if they're found
pub fn process_block(&self, b: Block, opts: Options)
-> Result<(Option<Tip>, Option<Block>), Error>
{
let res = self.process_block_no_orphans(b, opts);
match res {
Ok((t, b)) => {
// We accepted a block, so see if we can accept any orphans
if b.is_some() {
self.check_orphans(&b.clone().unwrap());
}
Ok((t, b))
},
Err(e) => {
Err(e)
}
}
}
/// Attempt to add a new block to the chain. Returns the new chain tip if it
/// has been added to the longest chain, None if it's added to an (as of
/// now) orphan chain.
pub fn process_block(&self, b: Block, opts: Options)
-> Result<Option<Tip>, Error>
pub fn process_block_no_orphans(&self, b: Block, opts: Options)
-> Result<(Option<Tip>, Option<Block>), Error>
{
let head = self.store
.head()
@ -223,8 +242,7 @@ impl Chain {
let adapter = self.adapter.clone();
adapter.block_accepted(&b);
}
// We just accepted a block so see if we can now accept any orphan(s)
self.check_orphans(&b);
Ok((Some(tip.clone()), Some(b.clone())))
},
Ok(None) => {
// block got accepted but we did not extend the head
@ -241,8 +259,7 @@ impl Chain {
let adapter = self.adapter.clone();
adapter.block_accepted(&b);
}
// We just accepted a block so see if we can now accept any orphan(s)
self.check_orphans(&b);
Ok((None, Some(b.clone())))
},
Err(Error::Orphan) => {
let block_hash = b.hash();
@ -264,6 +281,7 @@ impl Chain {
block_hash,
self.orphans.len(),
);
Err(Error::Orphan)
},
Err(Error::Unfit(ref msg)) => {
debug!(
@ -273,8 +291,9 @@ impl Chain {
b.header.height,
msg
);
Err(Error::Unfit(msg.clone()))
}
Err(ref e) => {
Err(e) => {
info!(
LOGGER,
"Rejected block {} at {}: {:?}",
@ -282,9 +301,9 @@ impl Chain {
b.header.height,
e
);
Err(e)
}
}
res
}
/// Attempt to add a new header to the header chain.
@ -316,19 +335,38 @@ impl Chain {
self.orphans.contains(hash)
}
fn check_orphans(&self, block: &Block) {
/// Check for orphans, once a block is successfully added
pub fn check_orphans(&self, block: &Block) {
debug!(
LOGGER,
"chain: check_orphans: # orphans {}",
self.orphans.len(),
);
let mut last_block_hash = block.hash();
// Is there an orphan in our orphans that we can now process?
// We just processed the given block, are there any orphans that have this block
// as their "previous" block?
if let Some(orphan) = self.orphans.get_by_previous(&block.hash()) {
self.orphans.remove(&orphan.block.hash());
let _ = self.process_block(orphan.block, orphan.opts);
loop {
if let Some(orphan) = self.orphans.get_by_previous(&last_block_hash) {
self.orphans.remove(&orphan.block.hash());
let res = self.process_block_no_orphans(orphan.block, orphan.opts);
match res {
Ok((_, b)) => {
// We accepted a block, so see if we can accept any orphans
if b.is_some() {
last_block_hash = b.unwrap().hash();
} else {
break;
}
},
Err(_) => {
break;
},
};
} else {
break;
}
}
}

View file

@ -75,15 +75,14 @@ impl p2p::ChainAdapter for NetToChainAdapter {
// pushing the new block through the chain pipeline
let res = self.chain.process_block(b, self.chain_opts());
if let &Err(ref e) = &res {
if let Err(ref e) = res {
debug!(LOGGER, "Block {} refused by chain: {:?}", bhash, e);
if e.is_bad_block() {
debug!(LOGGER, "block_received: {} is a bad block, resetting head", bhash);
let _ = self.chain.reset_head();
return false;
}
}
};
true
}