mirror of
https://github.com/mimblewimble/grin.git
synced 2025-02-08 12:21: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,
|
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
|
/// 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
|
/// has been added to the longest chain, None if it's added to an (as of
|
||||||
/// now) orphan chain.
|
/// now) orphan chain.
|
||||||
pub fn process_block(&self, b: Block, opts: Options)
|
pub fn process_block_no_orphans(&self, b: Block, opts: Options)
|
||||||
-> Result<Option<Tip>, Error>
|
-> Result<(Option<Tip>, Option<Block>), Error>
|
||||||
{
|
{
|
||||||
let head = self.store
|
let head = self.store
|
||||||
.head()
|
.head()
|
||||||
|
@ -223,8 +242,7 @@ impl Chain {
|
||||||
let adapter = self.adapter.clone();
|
let adapter = self.adapter.clone();
|
||||||
adapter.block_accepted(&b);
|
adapter.block_accepted(&b);
|
||||||
}
|
}
|
||||||
// We just accepted a block so see if we can now accept any orphan(s)
|
Ok((Some(tip.clone()), Some(b.clone())))
|
||||||
self.check_orphans(&b);
|
|
||||||
},
|
},
|
||||||
Ok(None) => {
|
Ok(None) => {
|
||||||
// block got accepted but we did not extend the head
|
// block got accepted but we did not extend the head
|
||||||
|
@ -241,8 +259,7 @@ impl Chain {
|
||||||
let adapter = self.adapter.clone();
|
let adapter = self.adapter.clone();
|
||||||
adapter.block_accepted(&b);
|
adapter.block_accepted(&b);
|
||||||
}
|
}
|
||||||
// We just accepted a block so see if we can now accept any orphan(s)
|
Ok((None, Some(b.clone())))
|
||||||
self.check_orphans(&b);
|
|
||||||
},
|
},
|
||||||
Err(Error::Orphan) => {
|
Err(Error::Orphan) => {
|
||||||
let block_hash = b.hash();
|
let block_hash = b.hash();
|
||||||
|
@ -264,6 +281,7 @@ impl Chain {
|
||||||
block_hash,
|
block_hash,
|
||||||
self.orphans.len(),
|
self.orphans.len(),
|
||||||
);
|
);
|
||||||
|
Err(Error::Orphan)
|
||||||
},
|
},
|
||||||
Err(Error::Unfit(ref msg)) => {
|
Err(Error::Unfit(ref msg)) => {
|
||||||
debug!(
|
debug!(
|
||||||
|
@ -273,8 +291,9 @@ impl Chain {
|
||||||
b.header.height,
|
b.header.height,
|
||||||
msg
|
msg
|
||||||
);
|
);
|
||||||
|
Err(Error::Unfit(msg.clone()))
|
||||||
}
|
}
|
||||||
Err(ref e) => {
|
Err(e) => {
|
||||||
info!(
|
info!(
|
||||||
LOGGER,
|
LOGGER,
|
||||||
"Rejected block {} at {}: {:?}",
|
"Rejected block {} at {}: {:?}",
|
||||||
|
@ -282,9 +301,9 @@ impl Chain {
|
||||||
b.header.height,
|
b.header.height,
|
||||||
e
|
e
|
||||||
);
|
);
|
||||||
|
Err(e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
res
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempt to add a new header to the header chain.
|
/// Attempt to add a new header to the header chain.
|
||||||
|
@ -316,19 +335,38 @@ impl Chain {
|
||||||
self.orphans.contains(hash)
|
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!(
|
debug!(
|
||||||
LOGGER,
|
LOGGER,
|
||||||
"chain: check_orphans: # orphans {}",
|
"chain: check_orphans: # orphans {}",
|
||||||
self.orphans.len(),
|
self.orphans.len(),
|
||||||
);
|
);
|
||||||
|
let mut last_block_hash = block.hash();
|
||||||
// Is there an orphan in our orphans that we can now process?
|
// 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
|
// We just processed the given block, are there any orphans that have this block
|
||||||
// as their "previous" block?
|
// as their "previous" block?
|
||||||
if let Some(orphan) = self.orphans.get_by_previous(&block.hash()) {
|
loop {
|
||||||
self.orphans.remove(&orphan.block.hash());
|
if let Some(orphan) = self.orphans.get_by_previous(&last_block_hash) {
|
||||||
let _ = self.process_block(orphan.block, orphan.opts);
|
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
|
// pushing the new block through the chain pipeline
|
||||||
let res = self.chain.process_block(b, self.chain_opts());
|
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);
|
debug!(LOGGER, "Block {} refused by chain: {:?}", bhash, e);
|
||||||
if e.is_bad_block() {
|
if e.is_bad_block() {
|
||||||
debug!(LOGGER, "block_received: {} is a bad block, resetting head", bhash);
|
debug!(LOGGER, "block_received: {} is a bad block, resetting head", bhash);
|
||||||
let _ = self.chain.reset_head();
|
let _ = self.chain.reset_head();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue