Move consensus error code to submodule
The `consensus` module has a bunch of error types, move them all to a separate module. Add re-exports so the types are still available at the same place they were. Make the `error` module private and re-export all errors from the `consensus` module root.
This commit is contained in:
parent
8de5432de9
commit
a6254212dc
|
@ -14,132 +14,29 @@
|
||||||
//! scripts come with an opcode decode, hashes are big-endian, numbers are
|
//! scripts come with an opcode decode, hashes are big-endian, numbers are
|
||||||
//! typically big-endian decimals, etc.)
|
//! typically big-endian decimals, etc.)
|
||||||
|
|
||||||
use core::{fmt, mem};
|
use core::mem;
|
||||||
|
|
||||||
use hashes::{sha256, sha256d, GeneralHash, Hash};
|
use hashes::{sha256, sha256d, GeneralHash, Hash};
|
||||||
use hex::error::{InvalidCharError, OddLengthStringError};
|
use hex::DisplayHex as _;
|
||||||
use internals::{compact_size, write_err, ToU64};
|
use internals::{compact_size, ToU64};
|
||||||
use io::{BufRead, Cursor, Read, Write};
|
use io::{BufRead, Cursor, Read, Write};
|
||||||
|
|
||||||
|
use super::IterReader;
|
||||||
use crate::bip152::{PrefilledTransaction, ShortId};
|
use crate::bip152::{PrefilledTransaction, ShortId};
|
||||||
use crate::bip158::{FilterHash, FilterHeader};
|
use crate::bip158::{FilterHash, FilterHeader};
|
||||||
use crate::block::{self, BlockHash};
|
use crate::block::{self, BlockHash};
|
||||||
use crate::consensus::{DecodeError, IterReader};
|
|
||||||
use crate::merkle_tree::TxMerkleNode;
|
use crate::merkle_tree::TxMerkleNode;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use crate::p2p::{
|
use crate::p2p::{
|
||||||
address::{AddrV2Message, Address},
|
address::{AddrV2Message, Address},
|
||||||
message_blockdata::Inventory,
|
message_blockdata::Inventory,
|
||||||
};
|
};
|
||||||
use crate::prelude::{rc, sync, Box, Cow, DisplayHex, String, Vec};
|
use crate::prelude::{rc, sync, Box, Cow, String, Vec};
|
||||||
use crate::taproot::TapLeafHash;
|
use crate::taproot::TapLeafHash;
|
||||||
use crate::transaction::{Transaction, TxIn, TxOut};
|
use crate::transaction::{Transaction, TxIn, TxOut};
|
||||||
|
|
||||||
/// Encoding error.
|
#[rustfmt::skip] // Keep public re-exports separate.
|
||||||
#[derive(Debug)]
|
pub use super::{Error, FromHexError};
|
||||||
#[non_exhaustive]
|
|
||||||
pub enum Error {
|
|
||||||
/// And I/O error.
|
|
||||||
Io(io::Error),
|
|
||||||
/// Tried to allocate an oversized vector.
|
|
||||||
OversizedVectorAllocation {
|
|
||||||
/// The capacity requested.
|
|
||||||
requested: usize,
|
|
||||||
/// The maximum capacity.
|
|
||||||
max: usize,
|
|
||||||
},
|
|
||||||
/// Checksum was invalid.
|
|
||||||
InvalidChecksum {
|
|
||||||
/// The expected checksum.
|
|
||||||
expected: [u8; 4],
|
|
||||||
/// The invalid checksum.
|
|
||||||
actual: [u8; 4],
|
|
||||||
},
|
|
||||||
/// VarInt was encoded in a non-minimal way.
|
|
||||||
NonMinimalVarInt,
|
|
||||||
/// Parsing error.
|
|
||||||
ParseFailed(&'static str),
|
|
||||||
/// Unsupported Segwit flag.
|
|
||||||
UnsupportedSegwitFlag(u8),
|
|
||||||
}
|
|
||||||
|
|
||||||
internals::impl_from_infallible!(Error);
|
|
||||||
|
|
||||||
impl fmt::Display for Error {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
use Error::*;
|
|
||||||
|
|
||||||
match *self {
|
|
||||||
Io(ref e) => write_err!(f, "IO error"; e),
|
|
||||||
OversizedVectorAllocation { requested: ref r, max: ref m } =>
|
|
||||||
write!(f, "allocation of oversized vector: requested {}, maximum {}", r, m),
|
|
||||||
InvalidChecksum { expected: ref e, actual: ref a } =>
|
|
||||||
write!(f, "invalid checksum: expected {:x}, actual {:x}", e.as_hex(), a.as_hex()),
|
|
||||||
NonMinimalVarInt => write!(f, "non-minimal varint"),
|
|
||||||
ParseFailed(ref s) => write!(f, "parse failed: {}", s),
|
|
||||||
UnsupportedSegwitFlag(ref swflag) =>
|
|
||||||
write!(f, "unsupported segwit version: {}", swflag),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
impl std::error::Error for Error {
|
|
||||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
|
||||||
use Error::*;
|
|
||||||
|
|
||||||
match self {
|
|
||||||
Io(e) => Some(e),
|
|
||||||
OversizedVectorAllocation { .. }
|
|
||||||
| InvalidChecksum { .. }
|
|
||||||
| NonMinimalVarInt
|
|
||||||
| ParseFailed(_)
|
|
||||||
| UnsupportedSegwitFlag(_) => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<io::Error> for Error {
|
|
||||||
fn from(error: io::Error) -> Self { Error::Io(error) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Hex deserialization error.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum FromHexError {
|
|
||||||
/// Purported hex string had odd length.
|
|
||||||
OddLengthString(OddLengthStringError),
|
|
||||||
/// Decoding error.
|
|
||||||
Decode(DecodeError<InvalidCharError>),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for FromHexError {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
use FromHexError::*;
|
|
||||||
|
|
||||||
match *self {
|
|
||||||
OddLengthString(ref e) =>
|
|
||||||
write_err!(f, "odd length, failed to create bytes from hex"; e),
|
|
||||||
Decode(ref e) => write_err!(f, "decoding error"; e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
impl std::error::Error for FromHexError {
|
|
||||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
|
||||||
use FromHexError::*;
|
|
||||||
|
|
||||||
match *self {
|
|
||||||
OddLengthString(ref e) => Some(e),
|
|
||||||
Decode(ref e) => Some(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<OddLengthStringError> for FromHexError {
|
|
||||||
#[inline]
|
|
||||||
fn from(e: OddLengthStringError) -> Self { Self::OddLengthString(e) }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Encodes an object into a vector.
|
/// Encodes an object into a vector.
|
||||||
pub fn serialize<T: Encodable + ?Sized>(data: &T) -> Vec<u8> {
|
pub fn serialize<T: Encodable + ?Sized>(data: &T) -> Vec<u8> {
|
||||||
|
@ -859,6 +756,7 @@ impl Decodable for TapLeafHash {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use core::fmt;
|
||||||
use core::mem::discriminant;
|
use core::mem::discriminant;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
|
@ -0,0 +1,157 @@
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
//! Consensus encoding errors.
|
||||||
|
|
||||||
|
use core::fmt;
|
||||||
|
|
||||||
|
use hex::error::{InvalidCharError, OddLengthStringError};
|
||||||
|
use hex::DisplayHex as _;
|
||||||
|
use internals::write_err;
|
||||||
|
|
||||||
|
#[cfg(doc)]
|
||||||
|
use super::IterReader;
|
||||||
|
|
||||||
|
/// Error when consensus decoding from an `[IterReader]`.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum DecodeError<E> {
|
||||||
|
/// Attempted to decode an object from an iterator that yielded too many bytes.
|
||||||
|
TooManyBytes,
|
||||||
|
/// Invalid consensus encoding.
|
||||||
|
Consensus(Error),
|
||||||
|
/// Other decoding error.
|
||||||
|
Other(E),
|
||||||
|
}
|
||||||
|
|
||||||
|
internals::impl_from_infallible!(DecodeError<E>);
|
||||||
|
|
||||||
|
impl<E: fmt::Debug> fmt::Display for DecodeError<E> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
use DecodeError::*;
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
TooManyBytes =>
|
||||||
|
write!(f, "attempted to decode object from an iterator that yielded too many bytes"),
|
||||||
|
Consensus(ref e) => write_err!(f, "invalid consensus encoding"; e),
|
||||||
|
Other(ref other) => write!(f, "other decoding error: {:?}", other),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl<E: fmt::Debug> std::error::Error for DecodeError<E> {
|
||||||
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
|
use DecodeError::*;
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
TooManyBytes => None,
|
||||||
|
Consensus(ref e) => Some(e),
|
||||||
|
Other(_) => None, // TODO: Is this correct?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Encoding error.
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[non_exhaustive]
|
||||||
|
pub enum Error {
|
||||||
|
/// And I/O error.
|
||||||
|
Io(io::Error),
|
||||||
|
/// Tried to allocate an oversized vector.
|
||||||
|
OversizedVectorAllocation {
|
||||||
|
/// The capacity requested.
|
||||||
|
requested: usize,
|
||||||
|
/// The maximum capacity.
|
||||||
|
max: usize,
|
||||||
|
},
|
||||||
|
/// Checksum was invalid.
|
||||||
|
InvalidChecksum {
|
||||||
|
/// The expected checksum.
|
||||||
|
expected: [u8; 4],
|
||||||
|
/// The invalid checksum.
|
||||||
|
actual: [u8; 4],
|
||||||
|
},
|
||||||
|
/// VarInt was encoded in a non-minimal way.
|
||||||
|
NonMinimalVarInt,
|
||||||
|
/// Parsing error.
|
||||||
|
ParseFailed(&'static str),
|
||||||
|
/// Unsupported Segwit flag.
|
||||||
|
UnsupportedSegwitFlag(u8),
|
||||||
|
}
|
||||||
|
|
||||||
|
internals::impl_from_infallible!(Error);
|
||||||
|
|
||||||
|
impl fmt::Display for Error {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
use Error::*;
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
Io(ref e) => write_err!(f, "IO error"; e),
|
||||||
|
OversizedVectorAllocation { requested: ref r, max: ref m } =>
|
||||||
|
write!(f, "allocation of oversized vector: requested {}, maximum {}", r, m),
|
||||||
|
InvalidChecksum { expected: ref e, actual: ref a } =>
|
||||||
|
write!(f, "invalid checksum: expected {:x}, actual {:x}", e.as_hex(), a.as_hex()),
|
||||||
|
NonMinimalVarInt => write!(f, "non-minimal varint"),
|
||||||
|
ParseFailed(ref s) => write!(f, "parse failed: {}", s),
|
||||||
|
UnsupportedSegwitFlag(ref swflag) =>
|
||||||
|
write!(f, "unsupported segwit version: {}", swflag),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl std::error::Error for Error {
|
||||||
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
|
use Error::*;
|
||||||
|
|
||||||
|
match self {
|
||||||
|
Io(e) => Some(e),
|
||||||
|
OversizedVectorAllocation { .. }
|
||||||
|
| InvalidChecksum { .. }
|
||||||
|
| NonMinimalVarInt
|
||||||
|
| ParseFailed(_)
|
||||||
|
| UnsupportedSegwitFlag(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<io::Error> for Error {
|
||||||
|
fn from(error: io::Error) -> Self { Error::Io(error) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Hex deserialization error.
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum FromHexError {
|
||||||
|
/// Purported hex string had odd length.
|
||||||
|
OddLengthString(OddLengthStringError),
|
||||||
|
/// Decoding error.
|
||||||
|
Decode(DecodeError<InvalidCharError>),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for FromHexError {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
use FromHexError::*;
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
OddLengthString(ref e) =>
|
||||||
|
write_err!(f, "odd length, failed to create bytes from hex"; e),
|
||||||
|
Decode(ref e) => write_err!(f, "decoding error"; e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl std::error::Error for FromHexError {
|
||||||
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||||
|
use FromHexError::*;
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
OddLengthString(ref e) => Some(e),
|
||||||
|
Decode(ref e) => Some(e),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<OddLengthStringError> for FromHexError {
|
||||||
|
#[inline]
|
||||||
|
fn from(e: OddLengthStringError) -> Self { Self::OddLengthString(e) }
|
||||||
|
}
|
|
@ -6,12 +6,12 @@
|
||||||
//! conform to Bitcoin consensus.
|
//! conform to Bitcoin consensus.
|
||||||
|
|
||||||
pub mod encode;
|
pub mod encode;
|
||||||
|
mod error;
|
||||||
#[cfg(feature = "serde")]
|
#[cfg(feature = "serde")]
|
||||||
pub mod serde;
|
pub mod serde;
|
||||||
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
|
|
||||||
use internals::write_err;
|
|
||||||
use io::{BufRead, Read};
|
use io::{BufRead, Read};
|
||||||
|
|
||||||
use crate::consensus;
|
use crate::consensus;
|
||||||
|
@ -20,6 +20,7 @@ use crate::consensus;
|
||||||
#[doc(inline)]
|
#[doc(inline)]
|
||||||
pub use self::{
|
pub use self::{
|
||||||
encode::{deserialize, deserialize_partial, serialize, Decodable, Encodable, ReadExt, WriteExt},
|
encode::{deserialize, deserialize_partial, serialize, Decodable, Encodable, ReadExt, WriteExt},
|
||||||
|
error::{Error, FromHexError, DecodeError},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IterReader<E: fmt::Debug, I: Iterator<Item = Result<u8, E>>> {
|
struct IterReader<E: fmt::Debug, I: Iterator<Item = Result<u8, E>>> {
|
||||||
|
@ -102,42 +103,3 @@ impl<E: fmt::Debug, I: Iterator<Item = Result<u8, E>>> BufRead for IterReader<E,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Error when consensus decoding from an `[IterReader]`.
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub enum DecodeError<E> {
|
|
||||||
/// Attempted to decode an object from an iterator that yielded too many bytes.
|
|
||||||
TooManyBytes,
|
|
||||||
/// Invalid consensus encoding.
|
|
||||||
Consensus(consensus::encode::Error),
|
|
||||||
/// Other decoding error.
|
|
||||||
Other(E),
|
|
||||||
}
|
|
||||||
|
|
||||||
internals::impl_from_infallible!(DecodeError<E>);
|
|
||||||
|
|
||||||
impl<E: fmt::Debug> fmt::Display for DecodeError<E> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
||||||
use DecodeError::*;
|
|
||||||
|
|
||||||
match *self {
|
|
||||||
TooManyBytes =>
|
|
||||||
write!(f, "attempted to decode object from an iterator that yielded too many bytes"),
|
|
||||||
Consensus(ref e) => write_err!(f, "invalid consensus encoding"; e),
|
|
||||||
Other(ref other) => write!(f, "other decoding error: {:?}", other),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
impl<E: fmt::Debug> std::error::Error for DecodeError<E> {
|
|
||||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
|
||||||
use DecodeError::*;
|
|
||||||
|
|
||||||
match *self {
|
|
||||||
TooManyBytes => None,
|
|
||||||
Consensus(ref e) => Some(e),
|
|
||||||
Other(_) => None, // TODO: Is this correct?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue