Check proof-of-work in the CheckpointVerifier

These checks make some resource exhaustion attacks harder to carry out,
because the malicious blocks need a valid proof-of-work.
This commit is contained in:
teor 2021-03-11 12:11:19 +10:00
parent c1a910942d
commit 8103e89739
1 changed files with 20 additions and 5 deletions

View File

@ -438,16 +438,25 @@ where
} }
} }
/// Check that the block height and Merkle root are valid. /// Check that the block height, proof of work, and Merkle root are valid.
///
/// ## Security
///
/// Checking the proof of work makes resource exhaustion attacks harder to
/// carry out, because malicious blocks require a valid proof of work.
/// ///
/// Checking the Merkle root ensures that the block hash binds the block /// Checking the Merkle root ensures that the block hash binds the block
/// contents. To prevent malleability (CVE-2012-2459), we also need to check /// contents. To prevent malleability (CVE-2012-2459), we also need to check
/// whether the transaction hashes are unique. /// whether the transaction hashes are unique.
fn check_block(&self, block: &Block) -> Result<block::Height, VerifyCheckpointError> { fn check_block(&self, block: &Block) -> Result<block::Height, VerifyCheckpointError> {
let block_height = block let hash = block.hash();
let height = block
.coinbase_height() .coinbase_height()
.ok_or(VerifyCheckpointError::CoinbaseHeight { hash: block.hash() })?; .ok_or(VerifyCheckpointError::CoinbaseHeight { hash })?;
self.check_height(block_height)?; self.check_height(height)?;
crate::block::check::difficulty_is_valid(&block.header, self.network, &height, &hash)?;
crate::block::check::equihash_solution_is_valid(&block.header)?;
let transaction_hashes = block let transaction_hashes = block
.transactions .transactions
@ -457,7 +466,7 @@ where
crate::block::check::merkle_root_validity(&block, &transaction_hashes)?; crate::block::check::merkle_root_validity(&block, &transaction_hashes)?;
Ok(block_height) Ok(height)
} }
/// Queue `block` for verification, and return the `Receiver` for the /// Queue `block` for verification, and return the `Receiver` for the
@ -842,6 +851,12 @@ impl From<BlockError> for VerifyCheckpointError {
} }
} }
impl From<equihash::Error> for VerifyCheckpointError {
fn from(err: equihash::Error) -> VerifyCheckpointError {
VerifyCheckpointError::VerifyBlock(err.into())
}
}
/// The CheckpointVerifier service implementation. /// The CheckpointVerifier service implementation.
/// ///
/// After verification, the block futures resolve to their hashes. /// After verification, the block futures resolve to their hashes.