verify_cut_through and test coverage (#3424)
* fix inconsistent verify_cut_through() logic * add test coverage for chain::process_block() and cut_through logic * fix comment
This commit is contained in:
+18
-1
@@ -486,7 +486,8 @@ impl Chain {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn new_ctx<'a>(
|
||||
/// Build a new block processing context.
|
||||
pub fn new_ctx<'a>(
|
||||
&self,
|
||||
opts: Options,
|
||||
batch: store::Batch<'a>,
|
||||
@@ -691,6 +692,22 @@ impl Chain {
|
||||
})
|
||||
}
|
||||
|
||||
/// Sets prev_root on a brand new block header by applying the previous header to the header MMR.
|
||||
pub fn set_prev_root_only(&self, header: &mut BlockHeader) -> Result<(), Error> {
|
||||
let mut header_pmmr = self.header_pmmr.write();
|
||||
let prev_root =
|
||||
txhashset::header_extending_readonly(&mut header_pmmr, &self.store(), |ext, batch| {
|
||||
let prev_header = batch.get_previous_header(header)?;
|
||||
pipe::rewind_and_apply_header_fork(&prev_header, ext, batch)?;
|
||||
ext.root()
|
||||
})?;
|
||||
|
||||
// Set the prev_root on the header.
|
||||
header.prev_root = prev_root;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Sets the txhashset roots on a brand new block by applying the block on
|
||||
/// the current txhashset state.
|
||||
pub fn set_txhashset_roots(&self, b: &mut Block) -> Result<(), Error> {
|
||||
|
||||
+3
-1
@@ -588,7 +588,9 @@ pub fn rewind_and_apply_fork(
|
||||
Ok(fork_point)
|
||||
}
|
||||
|
||||
/// Validate block inputs against utxo.
|
||||
/// Validate block inputs and outputs against utxo.
|
||||
/// Every input must spend an unspent output.
|
||||
/// No duplicate outputs created.
|
||||
fn validate_utxo(
|
||||
block: &Block,
|
||||
ext: &mut txhashset::ExtensionPair<'_>,
|
||||
|
||||
@@ -766,6 +766,38 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
/// Start a new readonly header MMR extension.
|
||||
/// This MMR can be extended individually beyond the other (output, rangeproof and kernel) MMRs
|
||||
/// to allow headers to be validated before we receive the full block data.
|
||||
pub fn header_extending_readonly<'a, F, T>(
|
||||
handle: &'a mut PMMRHandle<BlockHeader>,
|
||||
store: &ChainStore,
|
||||
inner: F,
|
||||
) -> Result<T, Error>
|
||||
where
|
||||
F: FnOnce(&mut HeaderExtension<'_>, &Batch<'_>) -> Result<T, Error>,
|
||||
{
|
||||
let batch = store.batch()?;
|
||||
|
||||
// Note: Extending either the sync_head or header_head MMR here.
|
||||
// Use underlying MMR to determine the "head".
|
||||
let head = match handle.head_hash() {
|
||||
Ok(hash) => {
|
||||
let header = batch.get_block_header(&hash)?;
|
||||
Tip::from_header(&header)
|
||||
}
|
||||
Err(_) => Tip::default(),
|
||||
};
|
||||
|
||||
let pmmr = PMMR::at(&mut handle.backend, handle.last_pos);
|
||||
let mut extension = HeaderExtension::new(pmmr, head);
|
||||
let res = inner(&mut extension, &batch);
|
||||
|
||||
handle.backend.discard();
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
/// Start a new header MMR unit of work.
|
||||
/// This MMR can be extended individually beyond the other (output, rangeproof and kernel) MMRs
|
||||
/// to allow headers to be validated before we receive the full block data.
|
||||
|
||||
Reference in New Issue
Block a user