• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tari-project / tari / 14729461626

29 Apr 2025 10:51AM UTC coverage: 69.15% (-4.3%) from 73.439%
14729461626

push

github

SWvheerden
new release

4 of 4 new or added lines in 2 files covered. (100.0%)

7663 existing lines in 132 files now uncovered.

76816 of 111086 relevant lines covered (69.15%)

237945.71 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

15.09
/base_layer/core/src/validation/error.rs
1
// Copyright 2019. The Tari Project
2
//
3
// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
4
// following conditions are met:
5
//
6
// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
7
// disclaimer.
8
//
9
// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the
10
// following disclaimer in the documentation and/or other materials provided with the distribution.
11
//
12
// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
13
// products derived from this software without specific prior written permission.
14
//
15
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
16
// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
20
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
21
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
22

23
use tari_common_types::types::HashOutput;
24
use tari_utilities::ByteArrayError;
25
use thiserror::Error;
26

27
use crate::{
28
    blocks::{BlockHeaderValidationError, BlockValidationError},
29
    chain_storage::ChainStorageError,
30
    common::{BanPeriod, BanReason},
31
    covenants::CovenantError,
32
    proof_of_work::{monero_rx::MergeMineError, DifficultyError, PowError},
33
    transactions::{
34
        tari_amount::MicroMinotari,
35
        transaction_components::{OutputType, RangeProofType, TransactionError},
36
    },
37
};
38

39
#[derive(Debug, Error)]
40
pub enum ValidationError {
41
    #[error("Serialization failed: {0}")]
42
    SerializationError(String),
43
    #[error("Block header validation failed: {0}")]
44
    BlockHeaderError(#[from] BlockHeaderValidationError),
45
    #[error("Block validation error: {0}")]
46
    BlockError(#[from] BlockValidationError),
47
    #[error("Contains kernels or inputs that are not yet spendable")]
48
    MaturityError,
49
    #[error("The block weight ({actual_weight}) is above the maximum ({max_weight})")]
50
    BlockTooLarge { actual_weight: u64, max_weight: u64 },
51
    #[error("Contains {} unknown inputs", .0.len())]
52
    UnknownInputs(Vec<HashOutput>),
53
    #[error("Contains an unknown input")]
54
    UnknownInput,
55
    #[error("The transaction is invalid: {0}")]
56
    TransactionError(#[from] TransactionError),
57
    #[error("Fatal storage error during validation: {0}")]
58
    FatalStorageError(String),
59
    #[error(
60
        "The total expected supply plus the total accumulated (offset) excess does not equal the sum of all UTXO \
61
         commitments."
62
    )]
63
    InvalidAccountingBalance,
64
    #[error("Transaction contains already spent inputs")]
65
    ContainsSTxO,
66
    #[error("Transaction contains outputs that already exist")]
67
    ContainsTxO,
68
    #[error("Transaction contains an output commitment that already exists")]
69
    ContainsDuplicateUtxoCommitment,
70
    #[error("Final state validation failed: The UTXO set did not balance with the expected emission at height {0}")]
71
    ChainBalanceValidationFailed(u64),
72
    #[error("The total value + fees of the block exceeds the maximum allowance on chain")]
73
    CoinbaseExceedsMaxLimit,
74
    #[error("Proof of work error: {0}")]
75
    ProofOfWorkError(#[from] PowError),
76
    #[error("Attempted to validate genesis block")]
77
    ValidatingGenesis,
78
    #[error("Duplicate or unsorted input found in block body")]
79
    UnsortedOrDuplicateInput,
80
    #[error("Duplicate or unsorted output found in block body")]
81
    UnsortedOrDuplicateOutput,
82
    #[error("Duplicate or unsorted kernel found in block body")]
83
    UnsortedOrDuplicateKernel,
84
    #[error("Error in merge mine data:{0}")]
85
    MergeMineError(#[from] MergeMineError),
86
    #[error("Maximum transaction weight exceeded")]
87
    MaxTransactionWeightExceeded,
88
    #[error("Expected block height to be {expected}, but was {block_height}")]
89
    IncorrectHeight { expected: u64, block_height: u64 },
90
    #[error("Expected block previous hash to be {expected}, but was {block_hash}")]
91
    IncorrectPreviousHash { expected: String, block_hash: String },
92
    #[error("Bad block with hash '{hash}' and reason '{reason}' found")]
93
    BadBlockFound { hash: String, reason: String },
94
    #[error("Script exceeded maximum script size, expected less than {max_script_size} but was {actual_script_size}")]
95
    TariScriptExceedsMaxSize {
96
        max_script_size: usize,
97
        actual_script_size: usize,
98
    },
99
    #[error(
100
        "Encrypted data exceeded maximum encrytped data size, expected less than {max_encrypted_data_size} but was \
101
         {actual_encrypted_data_size}"
102
    )]
103
    EncryptedDataExceedsMaxSize {
104
        max_encrypted_data_size: usize,
105
        actual_encrypted_data_size: usize,
106
    },
107
    #[error("Consensus Error: {0}")]
108
    ConsensusError(String),
109
    #[error("Duplicate kernel Error: {0}")]
110
    DuplicateKernelError(String),
111
    #[error("Covenant failed to validate: {0}")]
112
    CovenantError(#[from] CovenantError),
113
    #[error("Invalid or unsupported blockchain version {version}")]
114
    InvalidBlockchainVersion { version: u16 },
115
    #[error("Contains Invalid Burn: {0}")]
116
    InvalidBurnError(String),
117
    #[error("Output type '{output_type}' is not permitted")]
118
    OutputTypeNotPermitted { output_type: OutputType },
119
    #[error("Range proof type '{range_proof_type}' is not permitted")]
120
    RangeProofTypeNotPermitted { range_proof_type: RangeProofType },
121
    #[error("Output type '{output_type}' is not matched to any range proof type")]
122
    OutputTypeNotMatchedToRangeProofType { output_type: OutputType },
123
    #[error("Validator registration has invalid minimum amount {actual}, must be at least {min}")]
124
    ValidatorNodeRegistrationMinDepositAmount { min: MicroMinotari, actual: MicroMinotari },
125
    #[error("Validator registration has invalid maturity {actual}, must be at least {min}")]
126
    ValidatorNodeRegistrationMinLockHeight { min: u64, actual: u64 },
127
    #[error("Validator node registration signature failed verification")]
128
    InvalidValidatorNodeSignature,
129
    #[error(
130
        "An unexpected number of timestamps were provided to the header validator. THIS IS A BUG. Expected \
131
         {expected}, got {actual}"
132
    )]
133
    IncorrectNumberOfTimestampsProvided { expected: u64, actual: u64 },
134
    #[error("Invalid difficulty: {0}")]
135
    DifficultyError(#[from] DifficultyError),
136
    #[error("Covenant too large. Max size: {max_size}, Actual size: {actual_size}")]
137
    CovenantTooLarge { max_size: usize, actual_size: usize },
138
    #[error("Invalid Serialized Public key: {0}")]
139
    InvalidSerializedPublicKey(String),
140
}
141

142
// ChainStorageError has a ValidationError variant, so to prevent a cyclic dependency we use a string representation in
143
// for storage errors that cause validation failures.
144
impl From<ChainStorageError> for ValidationError {
145
    fn from(err: ChainStorageError) -> Self {
×
146
        Self::FatalStorageError(err.to_string())
×
147
    }
×
148
}
149

150
impl From<ByteArrayError> for ValidationError {
151
    fn from(err: ByteArrayError) -> Self {
×
152
        Self::InvalidSerializedPublicKey(err.to_string())
×
153
    }
×
154
}
155

156
impl ValidationError {
157
    pub fn get_ban_reason(&self) -> Option<BanReason> {
2✔
158
        match self {
2✔
159
            ValidationError::ProofOfWorkError(e) => e.get_ban_reason(),
×
160
            err @ ValidationError::SerializationError(_) |
×
161
            err @ ValidationError::BlockHeaderError(_) |
2✔
162
            err @ ValidationError::BlockError(_) |
×
163
            err @ ValidationError::MaturityError |
×
164
            err @ ValidationError::BlockTooLarge { .. } |
×
165
            err @ ValidationError::UnknownInputs(_) |
×
166
            err @ ValidationError::UnknownInput |
×
167
            err @ ValidationError::TransactionError(_) |
×
168
            err @ ValidationError::InvalidAccountingBalance |
×
169
            err @ ValidationError::ContainsSTxO |
×
170
            err @ ValidationError::ContainsTxO |
×
171
            err @ ValidationError::ContainsDuplicateUtxoCommitment |
×
172
            err @ ValidationError::ChainBalanceValidationFailed(_) |
×
173
            err @ ValidationError::ValidatingGenesis |
×
174
            err @ ValidationError::UnsortedOrDuplicateInput |
×
175
            err @ ValidationError::UnsortedOrDuplicateOutput |
×
176
            err @ ValidationError::UnsortedOrDuplicateKernel |
×
177
            err @ ValidationError::MaxTransactionWeightExceeded |
×
178
            err @ ValidationError::IncorrectHeight { .. } |
×
179
            err @ ValidationError::IncorrectPreviousHash { .. } |
×
180
            err @ ValidationError::BadBlockFound { .. } |
×
181
            err @ ValidationError::TariScriptExceedsMaxSize { .. } |
×
182
            err @ ValidationError::EncryptedDataExceedsMaxSize { .. } |
×
UNCOV
183
            err @ ValidationError::ConsensusError(_) |
×
184
            err @ ValidationError::DuplicateKernelError(_) |
×
185
            err @ ValidationError::CovenantError(_) |
×
186
            err @ ValidationError::InvalidBlockchainVersion { .. } |
×
187
            err @ ValidationError::InvalidBurnError(_) |
×
188
            err @ ValidationError::OutputTypeNotPermitted { .. } |
×
189
            err @ ValidationError::RangeProofTypeNotPermitted { .. } |
×
190
            err @ ValidationError::OutputTypeNotMatchedToRangeProofType { .. } |
×
191
            err @ ValidationError::ValidatorNodeRegistrationMinDepositAmount { .. } |
×
192
            err @ ValidationError::ValidatorNodeRegistrationMinLockHeight { .. } |
×
193
            err @ ValidationError::InvalidValidatorNodeSignature |
×
194
            err @ ValidationError::DifficultyError(_) |
×
195
            err @ ValidationError::CoinbaseExceedsMaxLimit |
×
196
            err @ ValidationError::CovenantTooLarge { .. } |
×
197
            err @ ValidationError::InvalidSerializedPublicKey(_) => Some(BanReason {
2✔
198
                reason: err.to_string(),
2✔
199
                ban_duration: BanPeriod::Long,
2✔
200
            }),
2✔
201
            ValidationError::MergeMineError(e) => e.get_ban_reason(),
×
202
            ValidationError::FatalStorageError(_) | ValidationError::IncorrectNumberOfTimestampsProvided { .. } => None,
×
203
        }
204
    }
2✔
205
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc