mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-01 17:01:09 +03:00
* port of stack overflow fix from testnet to master * update process_block to encapsulate orphan check workflow
This commit is contained in:
parent
8710d52797
commit
2def215553
2 changed files with 53 additions and 16 deletions
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue