use crate::core::core::{block, committed, transaction};
use crate::core::ser;
use crate::keychain;
use crate::util::secp;
use crate::util::secp::pedersen::Commitment;
use failure::{Backtrace, Context, Fail};
use grin_store as store;
use std::fmt::{self, Display};
use std::io;
#[derive(Debug, Fail)]
pub struct Error {
inner: Context<ErrorKind>,
}
#[derive(Clone, Eq, PartialEq, Debug, Fail)]
pub enum ErrorKind {
#[fail(display = "Block is unfit: {}", _0)]
Unfit(String),
#[fail(display = "Orphan")]
Orphan,
#[fail(display = "Difficulty is too low compared to ours or the block PoW hash")]
DifficultyTooLow,
#[fail(display = "Addition of difficulties on all previous blocks is wrong")]
WrongTotalDifficulty,
#[fail(display = "Cuckoo Size too small")]
LowEdgebits,
#[fail(display = "Wrong scaling factor")]
InvalidScaling,
#[fail(display = "Invalid PoW")]
InvalidPow,
#[fail(display = "Old Block")]
OldBlock,
#[fail(display = "Invalid Block Proof")]
InvalidBlockProof(block::Error),
#[fail(display = "Invalid Block Time")]
InvalidBlockTime,
#[fail(display = "Invalid Block Height")]
InvalidBlockHeight,
#[fail(display = "Invalid Root")]
InvalidRoot,
#[fail(display = "Invalid MMR Size")]
InvalidMMRSize,
#[fail(display = "Keychain Error")]
Keychain(keychain::Error),
#[fail(display = "Secp Lib Error")]
Secp(secp::Error),
#[fail(display = "Already Spent: {:?}", _0)]
AlreadySpent(Commitment),
#[fail(display = "Duplicate Commitment: {:?}", _0)]
DuplicateCommitment(Commitment),
#[fail(display = "Attempt to spend immature coinbase")]
ImmatureCoinbase,
#[fail(display = "Error validating merkle proof")]
MerkleProof,
#[fail(display = "Output not found")]
OutputNotFound,
#[fail(display = "Rangeproof not found")]
RangeproofNotFound,
#[fail(display = "Tx kernel not found")]
TxKernelNotFound,
#[fail(display = "Output is spent")]
OutputSpent,
#[fail(display = "Invalid Block Version: {:?}", _0)]
InvalidBlockVersion(block::HeaderVersion),
#[fail(display = "Invalid TxHashSet: {}", _0)]
InvalidTxHashSet(String),
#[fail(display = "Store Error: {}, reason: {}", _1, _0)]
StoreErr(store::Error, String),
#[fail(display = "File Read Error: {}", _0)]
FileReadErr(String),
#[fail(display = "Serialization Error")]
SerErr(ser::Error),
#[fail(display = "TxHashSetErr: {}", _0)]
TxHashSetErr(String),
#[fail(display = "Transaction Lock Height")]
TxLockHeight,
#[fail(display = "Genesis Block Required")]
GenesisBlockRequired,
#[fail(display = "Transaction Validation Error: {:?}", _0)]
Transaction(transaction::Error),
#[fail(display = "Other Error: {}", _0)]
Other(String),
#[fail(display = "Committed Trait: Error summing and verifying kernel sums")]
Committed(committed::Error),
#[fail(display = "Stopped (Grin Shutting Down)")]
Stopped,
#[fail(display = "Roaring Bitmap error")]
Bitmap,
#[fail(display = "Sync error")]
SyncError(String),
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let cause = match self.cause() {
Some(c) => format!("{}", c),
None => String::from("Unknown"),
};
let backtrace = match self.backtrace() {
Some(b) => format!("{}", b),
None => String::from("Unknown"),
};
let output = format!(
"{} \n Cause: {} \n Backtrace: {}",
self.inner, cause, backtrace
);
Display::fmt(&output, f)
}
}
impl Error {
pub fn kind(&self) -> ErrorKind {
self.inner.get_context().clone()
}
pub fn cause(&self) -> Option<&dyn Fail> {
self.inner.cause()
}
pub fn backtrace(&self) -> Option<&Backtrace> {
self.inner.backtrace()
}
pub fn is_bad_data(&self) -> bool {
match self.kind() {
ErrorKind::Unfit(_)
| ErrorKind::Orphan
| ErrorKind::StoreErr(_, _)
| ErrorKind::SerErr(_)
| ErrorKind::TxHashSetErr(_)
| ErrorKind::GenesisBlockRequired
| ErrorKind::Other(_) => false,
_ => true,
}
}
}
impl From<ErrorKind> for Error {
fn from(kind: ErrorKind) -> Error {
Error {
inner: Context::new(kind),
}
}
}
impl From<Context<ErrorKind>> for Error {
fn from(inner: Context<ErrorKind>) -> Error {
Error { inner: inner }
}
}
impl From<block::Error> for Error {
fn from(error: block::Error) -> Error {
let ec = error.clone();
Error {
inner: error.context(ErrorKind::InvalidBlockProof(ec)),
}
}
}
impl From<store::Error> for Error {
fn from(error: store::Error) -> Error {
let ec = error.clone();
Error {
inner: error.context(ErrorKind::StoreErr(ec.clone(), format!("{:?}", ec))),
}
}
}
impl From<keychain::Error> for Error {
fn from(error: keychain::Error) -> Error {
Error {
inner: Context::new(ErrorKind::Keychain(error)),
}
}
}
impl From<transaction::Error> for Error {
fn from(error: transaction::Error) -> Error {
Error {
inner: Context::new(ErrorKind::Transaction(error)),
}
}
}
impl From<committed::Error> for Error {
fn from(error: committed::Error) -> Error {
Error {
inner: Context::new(ErrorKind::Committed(error)),
}
}
}
impl From<io::Error> for Error {
fn from(e: io::Error) -> Error {
Error {
inner: Context::new(ErrorKind::TxHashSetErr(e.to_string())),
}
}
}
impl From<secp::Error> for Error {
fn from(e: secp::Error) -> Error {
Error {
inner: Context::new(ErrorKind::Secp(e)),
}
}
}