1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// Copyright (C) 2019-2021 Aleo Systems Inc.
// This file is part of the snarkOS library.

// The snarkOS library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// The snarkOS library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with the snarkOS library. If not, see <https://www.gnu.org/licenses/>.

use snarkvm_algorithms::errors::CRHError;
use snarkvm_dpc::DPCError;
use snarkvm_objects::{BlockError, StorageError, TransactionError};
use snarkvm_posw::error::PoswError;

use std::fmt::Debug;

/// Possible block verification errors
#[derive(Debug, Error)]
pub enum ConsensusError {
    #[error("UTXO has already been spent {:?} index: {:?}", _0, _1)]
    AlreadySpent(Vec<u8>, u32),

    #[error("{}", _0)]
    BlockError(BlockError),

    #[error("Block is too large: {}. Exceeds {} maximum", _0, _1)]
    BlockTooLarge(usize, usize),

    #[error("A coinbase transaction already exists in the block")]
    CoinbaseTransactionAlreadyExists(),

    #[error("conflicting network ids: {}, {}", _0, _1)]
    ConflictingNetworkId(u8, u8),

    #[error("{}: {}", _0, _1)]
    Crate(&'static str, String),

    #[error("{}", _0)]
    CRHError(CRHError),

    #[error("wrong difficulty, expected {0} got {1}")]
    DifficultyMismatch(u64, u64),

    #[error("{}", _0)]
    DPCError(DPCError),

    #[error("timestamp more than 2 hours into the future {:?} actual {:?}", _0, _1)]
    FuturisticTimestamp(i64, i64),

    #[error("invalid block {:?}", _0)]
    InvalidBlock(Vec<u8>),

    #[error("invalid coinbase transaction")]
    InvalidCoinbaseTransaction,

    #[error("block transactions do not hash to merkle root {:?}", _0)]
    MerkleRoot(String),

    #[error("{}", _0)]
    Message(String),

    #[error("the block has multiple coinbase transactions: {:?}", _0)]
    MultipleCoinbaseTransactions(u32),

    #[error("nonce {:?} is greater than nonce limit {:?}", _0, _1)]
    NonceInvalid(u32, u32),

    #[error("all nonces have been tried for the current block header")]
    NonceLimitError,

    #[error("Missing genesis block")]
    NoGenesisBlock,

    #[error("expected {:?} actual {:?}", _0, _1)]
    NoParent(String, String),

    #[error("block subroots do not hash to the pedersen merkle root {0}")]
    PedersenMerkleRoot(String),

    #[error("header greater than difficulty target {:?} actual {:?}", _0, _1)]
    PowInvalid(u64, u64),

    #[error(transparent)]
    PoswError(#[from] PoswError),

    #[error("{}", _0)]
    StorageError(StorageError),

    #[error("timestamp {:?} is less than parent timestamp {:?}", _0, _1)]
    TimestampInvalid(i64, i64),

    #[error("{}", _0)]
    TransactionError(TransactionError),

    #[error("Transactions are spending more funds than they have available")]
    TransactionOverspending,

    #[error("The block is already known")]
    PreExistingBlock,
}

impl From<BlockError> for ConsensusError {
    fn from(error: BlockError) -> Self {
        ConsensusError::BlockError(error)
    }
}

impl From<CRHError> for ConsensusError {
    fn from(error: CRHError) -> Self {
        ConsensusError::CRHError(error)
    }
}

impl From<DPCError> for ConsensusError {
    fn from(error: DPCError) -> Self {
        ConsensusError::DPCError(error)
    }
}

impl From<StorageError> for ConsensusError {
    fn from(error: StorageError) -> Self {
        ConsensusError::StorageError(error)
    }
}

impl From<TransactionError> for ConsensusError {
    fn from(error: TransactionError) -> Self {
        ConsensusError::TransactionError(error)
    }
}

impl From<anyhow::Error> for ConsensusError {
    fn from(error: anyhow::Error) -> Self {
        ConsensusError::Crate("anyhow", format!("{:?}", error))
    }
}

impl From<std::io::Error> for ConsensusError {
    fn from(error: std::io::Error) -> Self {
        ConsensusError::Crate("std::io", format!("{:?}", error))
    }
}