Merge rust-bitcoin/rust-bitcoin#1874: Add `ValidationError`

0f74eb6876 Remove the unused crate::Error (Tobin C. Harding)
74154c2294 Add block::ValidationError (Tobin C. Harding)
3a9b5526b3 Move BlockHash From impls (Tobin C. Harding)

Pull request description:

  Remove the `crate::Error` and replace its usage with `block::ValidationError`.

ACKs for top commit:
  apoelstra:
    ACK 0f74eb6876
  Kixunil:
    ACK 0f74eb6876

Tree-SHA512: 80b2c98d3d8f7c3f060c8ea2d94e1ebe118c07d0dcf91f6d13aed00df2cb0b15bf5e295ec0976d88d81e029cf7d3e8e4a1fe70120db57e49bbd8dd229291836b
This commit is contained in:
Andrew Poelstra 2023-05-28 22:27:44 +00:00
commit 5729b034d8
No known key found for this signature in database
GPG Key ID: C588D63CE41B97C1
3 changed files with 45 additions and 61 deletions

View File

@ -16,7 +16,6 @@ use super::Weight;
use crate::blockdata::script; use crate::blockdata::script;
use crate::blockdata::transaction::Transaction; use crate::blockdata::transaction::Transaction;
use crate::consensus::{encode, Decodable, Encodable}; use crate::consensus::{encode, Decodable, Encodable};
use crate::error::Error::{self, BlockBadProofOfWork, BlockBadTarget};
pub use crate::hash_types::BlockHash; pub use crate::hash_types::BlockHash;
use crate::hash_types::{TxMerkleNode, WitnessCommitment, WitnessMerkleNode, Wtxid}; use crate::hash_types::{TxMerkleNode, WitnessCommitment, WitnessMerkleNode, Wtxid};
use crate::internal_macros::impl_consensus_encoding; use crate::internal_macros::impl_consensus_encoding;
@ -72,16 +71,16 @@ impl Header {
pub fn difficulty_float(&self) -> f64 { self.target().difficulty_float() } pub fn difficulty_float(&self) -> f64 { self.target().difficulty_float() }
/// Checks that the proof-of-work for the block is valid, returning the block hash. /// Checks that the proof-of-work for the block is valid, returning the block hash.
pub fn validate_pow(&self, required_target: Target) -> Result<BlockHash, Error> { pub fn validate_pow(&self, required_target: Target) -> Result<BlockHash, ValidationError> {
let target = self.target(); let target = self.target();
if target != required_target { if target != required_target {
return Err(BlockBadTarget); return Err(ValidationError::BadTarget);
} }
let block_hash = self.block_hash(); let block_hash = self.block_hash();
if target.is_met_by(block_hash) { if target.is_met_by(block_hash) {
Ok(block_hash) Ok(block_hash)
} else { } else {
Err(BlockBadProofOfWork) Err(ValidationError::BadProofOfWork)
} }
} }
@ -337,6 +336,22 @@ impl Block {
} }
} }
impl From<Header> for BlockHash {
fn from(header: Header) -> BlockHash { header.block_hash() }
}
impl From<&Header> for BlockHash {
fn from(header: &Header) -> BlockHash { header.block_hash() }
}
impl From<Block> for BlockHash {
fn from(block: Block) -> BlockHash { block.block_hash() }
}
impl From<&Block> for BlockHash {
fn from(block: &Block) -> BlockHash { block.block_hash() }
}
/// An error when looking up a BIP34 block height. /// An error when looking up a BIP34 block height.
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq)]
#[non_exhaustive] #[non_exhaustive]
@ -375,20 +390,35 @@ impl std::error::Error for Bip34Error {
} }
} }
impl From<Header> for BlockHash { /// A block validation error.
fn from(header: Header) -> BlockHash { header.block_hash() } #[derive(Debug, Clone, PartialEq, Eq)]
pub enum ValidationError {
/// The header hash is not below the target.
BadProofOfWork,
/// The `target` field of a block header did not match the expected difficulty.
BadTarget,
} }
impl From<&Header> for BlockHash { impl fmt::Display for ValidationError {
fn from(header: &Header) -> BlockHash { header.block_hash() } fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
use ValidationError::*;
match *self {
BadProofOfWork => f.write_str("block target correct but not attained"),
BadTarget => f.write_str("block target incorrect"),
}
}
} }
impl From<Block> for BlockHash { #[cfg(feature = "std")]
fn from(block: Block) -> BlockHash { block.block_hash() } impl std::error::Error for ValidationError {
} fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use self::ValidationError::*;
impl From<&Block> for BlockHash { match *self {
fn from(block: &Block) -> BlockHash { block.block_hash() } BadProofOfWork | BadTarget => None,
}
}
} }
#[cfg(test)] #[cfg(test)]
@ -528,7 +558,7 @@ mod tests {
// test with zero target // test with zero target
match some_header.validate_pow(Target::ZERO) { match some_header.validate_pow(Target::ZERO) {
Err(BlockBadTarget) => (), Err(ValidationError::BadTarget) => (),
_ => panic!("unexpected result from validate_pow"), _ => panic!("unexpected result from validate_pow"),
} }
@ -536,7 +566,7 @@ mod tests {
let mut invalid_header: Header = some_header; let mut invalid_header: Header = some_header;
invalid_header.version.0 += 1; invalid_header.version.0 += 1;
match invalid_header.validate_pow(invalid_header.target()) { match invalid_header.validate_pow(invalid_header.target()) {
Err(BlockBadProofOfWork) => (), Err(ValidationError::BadProofOfWork) => (),
_ => panic!("unexpected result from validate_pow"), _ => panic!("unexpected result from validate_pow"),
} }
} }

View File

@ -2,53 +2,8 @@
//! Contains error types and other error handling tools. //! Contains error types and other error handling tools.
use core::fmt;
use internals::write_err;
use crate::consensus::encode;
pub use crate::parse::ParseIntError; pub use crate::parse::ParseIntError;
/// A general error code, other errors should implement conversions to/from this
/// if appropriate.
#[derive(Debug)]
#[non_exhaustive]
pub enum Error {
/// Encoding error
Encode(encode::Error),
/// The header hash is not below the target
BlockBadProofOfWork,
/// The `target` field of a block header did not match the expected difficulty
BlockBadTarget,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Encode(ref e) => write_err!(f, "encoding error"; e),
Error::BlockBadProofOfWork => f.write_str("block target correct but not attained"),
Error::BlockBadTarget => f.write_str("block target incorrect"),
}
}
}
#[cfg(feature = "std")]
impl std::error::Error for Error {
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
use self::Error::*;
match self {
Encode(e) => Some(e),
BlockBadProofOfWork | BlockBadTarget => None,
}
}
}
#[doc(hidden)]
impl From<encode::Error> for Error {
fn from(e: encode::Error) -> Error { Error::Encode(e) }
}
/// Impls std::error::Error for the specified type with appropriate attributes, possibly returning /// Impls std::error::Error for the specified type with appropriate attributes, possibly returning
/// source. /// source.
macro_rules! impl_std_error { macro_rules! impl_std_error {

View File

@ -134,7 +134,6 @@ pub use crate::blockdata::{constants, opcodes};
pub use crate::consensus::encode::VarInt; pub use crate::consensus::encode::VarInt;
pub use crate::crypto::key::{self, PrivateKey, PublicKey}; pub use crate::crypto::key::{self, PrivateKey, PublicKey};
pub use crate::crypto::{ecdsa, sighash}; pub use crate::crypto::{ecdsa, sighash};
pub use crate::error::Error;
pub use crate::hash_types::{ pub use crate::hash_types::{
BlockHash, PubkeyHash, ScriptHash, Txid, WPubkeyHash, WScriptHash, Wtxid, BlockHash, PubkeyHash, ScriptHash, Txid, WPubkeyHash, WScriptHash, Wtxid,
}; };