Skip to main content

iota_types/block/
error.rs

1// Copyright 2020-2021 IOTA Stiftung
2// SPDX-License-Identifier: Apache-2.0
3
4use alloc::string::{FromUtf8Error, String};
5use core::{convert::Infallible, fmt};
6
7use crypto::Error as CryptoError;
8use prefix_hex::Error as HexError;
9use primitive_types::U256;
10
11use crate::block::{
12    input::UtxoInput,
13    output::{
14        feature::FeatureCount, unlock_condition::UnlockConditionCount, AliasId, ChainId, MetadataFeatureLength,
15        NativeTokenCount, NftId, OutputIndex, StateMetadataLength, TagFeatureLength,
16    },
17    parent::ParentCount,
18    payload::{
19        milestone::BinaryParametersLength, InputCount, MilestoneMetadataLength, MilestoneOptionCount, OutputCount,
20        ReceiptFundsCount, SignatureCount, TagLength, TaggedDataLength,
21    },
22    unlock::{UnlockCount, UnlockIndex},
23};
24
25/// Error occurring when creating/parsing/validating blocks.
26#[derive(Debug, PartialEq, Eq)]
27#[allow(missing_docs)]
28pub enum Error {
29    ConsumedAmountOverflow,
30    ConsumedNativeTokensAmountOverflow,
31    CreatedAmountOverflow,
32    CreatedNativeTokensAmountOverflow,
33    Crypto(CryptoError),
34    DuplicateSignatureUnlock(u16),
35    DuplicateUtxo(UtxoInput),
36    ExpirationUnlockConditionZero,
37    FeaturesNotUniqueSorted,
38    InputUnlockCountMismatch { input_count: usize, unlock_count: usize },
39    InvalidAddress,
40    InvalidAddressKind(u8),
41    InvalidAliasIndex(<UnlockIndex as TryFrom<u16>>::Error),
42    InvalidControllerKind(u8),
43    InvalidStorageDepositAmount(u64),
44    // The above is used by `Packable` to denote out-of-range values. The following denotes the actual amount.
45    InsufficientStorageDepositAmount { amount: u64, required: u64 },
46    StorageDepositReturnExceedsOutputAmount { deposit: u64, amount: u64 },
47    InsufficientStorageDepositReturnAmount { deposit: u64, required: u64 },
48    InvalidBinaryParametersLength(<BinaryParametersLength as TryFrom<usize>>::Error),
49    InvalidEssenceKind(u8),
50    InvalidFeatureCount(<FeatureCount as TryFrom<usize>>::Error),
51    InvalidFeatureKind(u8),
52    InvalidFoundryOutputSupply { minted: U256, melted: U256, max: U256 },
53    Hex(HexError),
54    InvalidInputKind(u8),
55    InvalidInputCount(<InputCount as TryFrom<usize>>::Error),
56    InvalidInputOutputIndex(<OutputIndex as TryFrom<u16>>::Error),
57    InvalidBech32Hrp(FromUtf8Error),
58    InvalidBlockLength(usize),
59    InvalidStateMetadataLength(<StateMetadataLength as TryFrom<usize>>::Error),
60    InvalidMetadataFeatureLength(<MetadataFeatureLength as TryFrom<usize>>::Error),
61    InvalidMilestoneMetadataLength(<MilestoneMetadataLength as TryFrom<usize>>::Error),
62    InvalidMilestoneOptionCount(<MilestoneOptionCount as TryFrom<usize>>::Error),
63    InvalidMilestoneOptionKind(u8),
64    InvalidMigratedFundsEntryAmount(u64),
65    InvalidNativeTokenCount(<NativeTokenCount as TryFrom<usize>>::Error),
66    InvalidNetworkName(FromUtf8Error),
67    InvalidNftIndex(<UnlockIndex as TryFrom<u16>>::Error),
68    InvalidOutputAmount(u64),
69    InvalidOutputCount(<OutputCount as TryFrom<usize>>::Error),
70    InvalidOutputKind(u8),
71    InvalidParentCount(<ParentCount as TryFrom<usize>>::Error),
72    InvalidPayloadKind(u32),
73    InvalidPayloadLength { expected: usize, actual: usize },
74    InvalidReceiptFundsCount(<ReceiptFundsCount as TryFrom<usize>>::Error),
75    InvalidReceiptFundsSum(u128),
76    InvalidReferenceIndex(<UnlockIndex as TryFrom<u16>>::Error),
77    InvalidSignature,
78    InvalidSignatureKind(u8),
79    InvalidStringPrefix(<u8 as TryFrom<usize>>::Error),
80    InvalidTaggedDataLength(<TaggedDataLength as TryFrom<usize>>::Error),
81    InvalidTagFeatureLength(<TagFeatureLength as TryFrom<usize>>::Error),
82    InvalidTagLength(<TagLength as TryFrom<usize>>::Error),
83    InvalidTailTransactionHash,
84    InvalidTokenSchemeKind(u8),
85    InvalidTransactionAmountSum(u128),
86    InvalidTransactionNativeTokensCount(u16),
87    InvalidTreasuryOutputAmount(u64),
88    InvalidUnlockCount(<UnlockCount as TryFrom<usize>>::Error),
89    InvalidUnlockKind(u8),
90    InvalidUnlockReference(u16),
91    InvalidUnlockAlias(u16),
92    InvalidUnlockNft(u16),
93    InvalidUnlockConditionCount(<UnlockConditionCount as TryFrom<usize>>::Error),
94    InvalidUnlockConditionKind(u8),
95    MigratedFundsNotSorted,
96    MilestoneInvalidSignatureCount(<SignatureCount as TryFrom<usize>>::Error),
97    MilestonePublicKeysSignaturesCountMismatch { key_count: usize, sig_count: usize },
98    MilestoneOptionsNotUniqueSorted,
99    MilestoneSignaturesNotUniqueSorted,
100    MissingAddressUnlockCondition,
101    MissingGovernorUnlockCondition,
102    MissingPayload,
103    MissingRequiredSenderBlock,
104    MissingStateControllerUnlockCondition,
105    NativeTokensNotUniqueSorted,
106    NativeTokensNullAmount,
107    NativeTokensOverflow,
108    NetworkIdMismatch { expected: u64, actual: u64 },
109    NonZeroStateIndexOrFoundryCounter,
110    ParentsNotUniqueSorted,
111    ProtocolVersionMismatch { expected: u8, actual: u8 },
112    NonceNotFound,
113    ReceiptFundsNotUniqueSorted,
114    RemainingBytesAfterBlock,
115    SelfControlledAliasOutput(AliasId),
116    SelfDepositNft(NftId),
117    SignaturePublicKeyMismatch { expected: String, actual: String },
118    StorageDepositReturnOverflow,
119    TailTransactionHashNotUnique { previous: usize, current: usize },
120    TimelockUnlockConditionZero,
121    UnallowedFeature { index: usize, kind: u8 },
122    UnallowedUnlockCondition { index: usize, kind: u8 },
123    UnlockConditionsNotUniqueSorted,
124    UnsupportedOutputKind(u8),
125    DuplicateOutputChain(ChainId),
126}
127
128#[cfg(feature = "std")]
129impl std::error::Error for Error {}
130
131impl fmt::Display for Error {
132    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133        match self {
134            Self::ConsumedAmountOverflow => write!(f, "consumed amount overflow"),
135            Self::ConsumedNativeTokensAmountOverflow => write!(f, "consumed native tokens amount overflow"),
136            Self::CreatedAmountOverflow => write!(f, "created amount overflow"),
137            Self::CreatedNativeTokensAmountOverflow => write!(f, "created native tokens amount overflow"),
138            Self::Crypto(e) => write!(f, "cryptographic error: {e}"),
139            Self::DuplicateSignatureUnlock(index) => {
140                write!(f, "duplicate signature unlock at index: {index}")
141            }
142            Self::DuplicateUtxo(utxo) => write!(f, "duplicate UTXO {utxo:?} in inputs"),
143            Self::ExpirationUnlockConditionZero => {
144                write!(
145                    f,
146                    "expiration unlock condition with milestone index and timestamp set to 0",
147                )
148            }
149            Self::FeaturesNotUniqueSorted => write!(f, "features are not unique and/or sorted"),
150            Self::InputUnlockCountMismatch {
151                input_count,
152                unlock_count,
153            } => {
154                write!(
155                    f,
156                    "input count and unlock count mismatch: {input_count} != {unlock_count}",
157                )
158            }
159            Self::InvalidAddress => write!(f, "invalid address provided"),
160            Self::InvalidAddressKind(k) => write!(f, "invalid address kind: {k}"),
161            Self::InvalidAliasIndex(index) => write!(f, "invalid alias index: {index}"),
162            Self::InvalidBech32Hrp(err) => write!(f, "invalid bech32 hrp: {err}"),
163            Self::InvalidBinaryParametersLength(length) => {
164                write!(f, "invalid binary parameters length: {length}")
165            }
166            Self::InvalidControllerKind(k) => write!(f, "invalid controller kind: {k}"),
167            Self::InvalidStorageDepositAmount(amount) => {
168                write!(f, "invalid storage deposit amount: {amount}")
169            }
170            Self::InsufficientStorageDepositAmount { amount, required } => {
171                write!(
172                    f,
173                    "insufficient output amount for storage deposit: {amount} (should be at least {required})"
174                )
175            }
176            Self::InsufficientStorageDepositReturnAmount { deposit, required } => {
177                write!(
178                    f,
179                    "the return deposit ({deposit}) must be greater than the minimum storage deposit ({required})"
180                )
181            }
182            Self::StorageDepositReturnExceedsOutputAmount { deposit, amount } => write!(
183                f,
184                "storage deposit return of {deposit} exceeds the original output amount of {amount}"
185            ),
186            Self::InvalidEssenceKind(k) => write!(f, "invalid essence kind: {k}"),
187            Self::InvalidFeatureCount(count) => write!(f, "invalid feature count: {count}"),
188            Self::InvalidFeatureKind(k) => write!(f, "invalid feature kind: {k}"),
189            Self::InvalidFoundryOutputSupply { minted, melted, max } => write!(
190                f,
191                "invalid foundry output supply: minted {minted}, melted {melted} max {max}",
192            ),
193            Self::Hex(error) => write!(f, "hex error: {error}"),
194            Self::InvalidInputKind(k) => write!(f, "invalid input kind: {k}"),
195            Self::InvalidInputCount(count) => write!(f, "invalid input count: {count}"),
196            Self::InvalidInputOutputIndex(index) => write!(f, "invalid input or output index: {index}"),
197            Self::InvalidBlockLength(length) => write!(f, "invalid block length {length}"),
198            Self::InvalidStateMetadataLength(length) => write!(f, "invalid state metadata length {length}"),
199            Self::InvalidMetadataFeatureLength(length) => {
200                write!(f, "invalid metadata feature length {length}")
201            }
202            Self::InvalidMilestoneMetadataLength(length) => {
203                write!(f, "invalid milestone metadata length {length}")
204            }
205            Self::InvalidMilestoneOptionCount(count) => write!(f, "invalid milestone option count: {count}"),
206            Self::InvalidMilestoneOptionKind(k) => write!(f, "invalid milestone option kind: {k}"),
207            Self::InvalidMigratedFundsEntryAmount(amount) => {
208                write!(f, "invalid migrated funds entry amount: {amount}")
209            }
210            Self::InvalidNativeTokenCount(count) => write!(f, "invalid native token count: {count}"),
211            Self::InvalidNetworkName(err) => write!(f, "invalid network name: {err}"),
212            Self::InvalidNftIndex(index) => write!(f, "invalid nft index: {index}"),
213            Self::InvalidOutputAmount(amount) => write!(f, "invalid output amount: {amount}"),
214            Self::InvalidOutputCount(count) => write!(f, "invalid output count: {count}"),
215            Self::InvalidOutputKind(k) => write!(f, "invalid output kind: {k}"),
216            Self::InvalidParentCount(count) => {
217                write!(f, "invalid parents count: {count}")
218            }
219            Self::InvalidPayloadKind(k) => write!(f, "invalid payload kind: {k}"),
220            Self::InvalidPayloadLength { expected, actual } => {
221                write!(f, "invalid payload length: expected {expected} but got {actual}")
222            }
223            Self::InvalidReceiptFundsCount(count) => write!(f, "invalid receipt funds count: {count}"),
224            Self::InvalidReceiptFundsSum(sum) => write!(f, "invalid receipt amount sum: {sum}"),
225            Self::InvalidReferenceIndex(index) => write!(f, "invalid reference index: {index}"),
226            Self::InvalidSignature => write!(f, "invalid signature provided"),
227            Self::InvalidSignatureKind(k) => write!(f, "invalid signature kind: {k}"),
228            Self::InvalidStringPrefix(p) => write!(f, "invalid string prefix: {p}"),
229            Self::InvalidTaggedDataLength(length) => {
230                write!(f, "invalid tagged data length {length}")
231            }
232            Self::InvalidTagFeatureLength(length) => {
233                write!(f, "invalid tag feature length {length}")
234            }
235            Self::InvalidTagLength(length) => {
236                write!(f, "invalid tag length {length}")
237            }
238            Self::InvalidTailTransactionHash => write!(f, "invalid tail transaction hash"),
239            Self::InvalidTokenSchemeKind(k) => write!(f, "invalid token scheme kind {k}"),
240            Self::InvalidTransactionAmountSum(value) => write!(f, "invalid transaction amount sum: {value}"),
241            Self::InvalidTransactionNativeTokensCount(count) => {
242                write!(f, "invalid transaction native tokens count: {count}")
243            }
244            Self::InvalidTreasuryOutputAmount(amount) => write!(f, "invalid treasury amount: {amount}"),
245            Self::InvalidUnlockCount(count) => write!(f, "invalid unlock count: {count}"),
246            Self::InvalidUnlockKind(k) => write!(f, "invalid unlock kind: {k}"),
247            Self::InvalidUnlockReference(index) => {
248                write!(f, "invalid unlock reference: {index}")
249            }
250            Self::InvalidUnlockAlias(index) => {
251                write!(f, "invalid unlock alias: {index}")
252            }
253            Self::InvalidUnlockNft(index) => {
254                write!(f, "invalid unlock nft: {index}")
255            }
256            Self::InvalidUnlockConditionCount(count) => write!(f, "invalid unlock condition count: {count}"),
257            Self::InvalidUnlockConditionKind(k) => write!(f, "invalid unlock condition kind: {k}"),
258            Self::MigratedFundsNotSorted => {
259                write!(f, "migrated funds are not sorted")
260            }
261            Self::MilestoneInvalidSignatureCount(count) => {
262                write!(f, "invalid milestone signature count: {count}")
263            }
264            Self::MilestonePublicKeysSignaturesCountMismatch { key_count, sig_count } => {
265                write!(
266                    f,
267                    "milestone public keys and signatures count mismatch: {key_count} != {sig_count}",
268                )
269            }
270            Self::MilestoneOptionsNotUniqueSorted => {
271                write!(f, "milestone options are not unique and/or sorted")
272            }
273            Self::MilestoneSignaturesNotUniqueSorted => {
274                write!(f, "milestone signatures are not unique and/or sorted")
275            }
276            Self::MissingAddressUnlockCondition => write!(f, "missing address unlock condition"),
277            Self::MissingGovernorUnlockCondition => write!(f, "missing governor unlock condition"),
278            Self::MissingPayload => write!(f, "missing payload"),
279            Self::MissingRequiredSenderBlock => write!(f, "missing required sender block"),
280            Self::MissingStateControllerUnlockCondition => write!(f, "missing state controller unlock condition"),
281            Self::NativeTokensNotUniqueSorted => write!(f, "native tokens are not unique and/or sorted"),
282            Self::NativeTokensNullAmount => write!(f, "native tokens null amount"),
283            Self::NativeTokensOverflow => write!(f, "native tokens overflow"),
284            Self::NetworkIdMismatch { expected, actual } => {
285                write!(f, "network ID mismatch: expected {expected} but got {actual}")
286            }
287            Self::NonZeroStateIndexOrFoundryCounter => {
288                write!(f, "non zero state index or foundry counter while alias ID is all zero")
289            }
290            Self::ParentsNotUniqueSorted => {
291                write!(f, "parents are not unique and/or sorted")
292            }
293            Self::ProtocolVersionMismatch { expected, actual } => {
294                write!(f, "protocol version mismatch: expected {expected} but got {actual}")
295            }
296            Self::NonceNotFound => {
297                write!(f, "nonce miner could not find a nonce")
298            }
299            Self::ReceiptFundsNotUniqueSorted => {
300                write!(f, "receipt funds are not unique and/or sorted")
301            }
302            Self::RemainingBytesAfterBlock => {
303                write!(f, "remaining bytes after block")
304            }
305            Self::SelfControlledAliasOutput(alias_id) => {
306                write!(f, "self controlled alias output, alias ID {alias_id}")
307            }
308            Self::SelfDepositNft(nft_id) => {
309                write!(f, "self deposit nft output, NFT ID {nft_id}")
310            }
311            Self::SignaturePublicKeyMismatch { expected, actual } => {
312                write!(f, "signature public key mismatch: expected {expected} but got {actual}",)
313            }
314            Self::StorageDepositReturnOverflow => {
315                write!(f, "storage deposit return overflow",)
316            }
317            Self::TailTransactionHashNotUnique { previous, current } => {
318                write!(
319                    f,
320                    "tail transaction hash is not unique at indices: {previous} and {current}",
321                )
322            }
323            Self::TimelockUnlockConditionZero => {
324                write!(
325                    f,
326                    "timelock unlock condition with milestone index and timestamp set to 0",
327                )
328            }
329            Self::UnallowedFeature { index, kind } => {
330                write!(f, "unallowed feature at index {index} with kind {kind}")
331            }
332            Self::UnallowedUnlockCondition { index, kind } => {
333                write!(f, "unallowed unlock condition at index {index} with kind {kind}")
334            }
335            Self::UnlockConditionsNotUniqueSorted => write!(f, "unlock conditions are not unique and/or sorted"),
336            Self::UnsupportedOutputKind(k) => write!(f, "unsupported output kind: {k}"),
337            Self::DuplicateOutputChain(chain_id) => write!(f, "duplicate output chain {chain_id}"),
338        }
339    }
340}
341
342impl From<CryptoError> for Error {
343    fn from(error: CryptoError) -> Self {
344        Self::Crypto(error)
345    }
346}
347
348impl From<Infallible> for Error {
349    fn from(error: Infallible) -> Self {
350        match error {}
351    }
352}
353
354#[cfg(feature = "dto")]
355#[allow(missing_docs)]
356pub mod dto {
357    use super::*;
358
359    #[derive(Debug)]
360    pub enum DtoError {
361        InvalidField(&'static str),
362        Block(Error),
363    }
364
365    impl fmt::Display for DtoError {
366        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
367            match self {
368                Self::InvalidField(field) => write!(f, "{field}"),
369                Self::Block(error) => write!(f, "{error}"),
370            }
371        }
372    }
373
374    impl From<Error> for DtoError {
375        fn from(error: Error) -> Self {
376            Self::Block(error)
377        }
378    }
379
380    #[cfg(feature = "std")]
381    impl std::error::Error for DtoError {}
382}